summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/vxlan.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 916a62149a12..a7fd9a089a35 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -98,6 +98,7 @@ struct vxlan_fdb {
unsigned long used;
struct vxlan_rdst remote;
u16 state; /* see ndm_state */
+ u8 flags; /* see ndm_flags */
u8 eth_addr[ETH_ALEN];
};
@@ -180,7 +181,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
ndm->ndm_family = AF_BRIDGE;
ndm->ndm_state = fdb->state;
ndm->ndm_ifindex = vxlan->dev->ifindex;
- ndm->ndm_flags = NTF_SELF;
+ ndm->ndm_flags = fdb->flags;
ndm->ndm_type = NDA_DST;
if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
@@ -343,7 +344,8 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
static int vxlan_fdb_create(struct vxlan_dev *vxlan,
const u8 *mac, __be32 ip,
__u16 state, __u16 flags,
- __u32 port, __u32 vni, __u32 ifindex)
+ __u32 port, __u32 vni, __u32 ifindex,
+ __u8 ndm_flags)
{
struct vxlan_fdb *f;
int notify = 0;
@@ -360,6 +362,11 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
f->updated = jiffies;
notify = 1;
}
+ if (f->flags != ndm_flags) {
+ f->flags = ndm_flags;
+ f->updated = jiffies;
+ notify = 1;
+ }
if ((flags & NLM_F_APPEND) &&
is_multicast_ether_addr(f->eth_addr)) {
int rc = vxlan_fdb_append(f, ip, port, vni, ifindex);
@@ -387,6 +394,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
f->remote.remote_ifindex = ifindex;
f->remote.remote_next = NULL;
f->state = state;
+ f->flags = ndm_flags;
f->updated = f->used = jiffies;
memcpy(f->eth_addr, mac, ETH_ALEN);
@@ -480,7 +488,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
spin_lock_bh(&vxlan->hash_lock);
err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags, port,
- vni, ifindex);
+ vni, ifindex, ndm->ndm_flags);
spin_unlock_bh(&vxlan->hash_lock);
return err;
@@ -568,7 +576,9 @@ static void vxlan_snoop(struct net_device *dev,
err = vxlan_fdb_create(vxlan, src_mac, src_ip,
NUD_REACHABLE,
NLM_F_EXCL|NLM_F_CREATE,
- vxlan_port, vxlan->default_dst.remote_vni, 0);
+ vxlan_port,
+ vxlan->default_dst.remote_vni,
+ 0, NTF_SELF);
spin_unlock(&vxlan->hash_lock);
}
}
@@ -1098,12 +1108,18 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
return arp_reduce(dev, skb);
- else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
- did_rsc = route_shortcircuit(dev, skb);
f = vxlan_find_mac(vxlan, eth->h_dest);
+ did_rsc = false;
+
+ if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) &&
+ ntohs(eth->h_proto) == ETH_P_IP) {
+ did_rsc = route_shortcircuit(dev, skb);
+ if (did_rsc)
+ f = vxlan_find_mac(vxlan, eth->h_dest);
+ }
+
if (f == NULL) {
- did_rsc = false;
rdst0 = &vxlan->default_dst;
if (rdst0->remote_ip == htonl(INADDR_ANY) &&