diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index c55e316373a1..4dbb2ed85b97 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -389,8 +389,8 @@ static inline size_t vxlan_nlmsg_size(void) | |||
389 | + nla_total_size(sizeof(struct nda_cacheinfo)); | 389 | + nla_total_size(sizeof(struct nda_cacheinfo)); |
390 | } | 390 | } |
391 | 391 | ||
392 | static void vxlan_fdb_notify(struct vxlan_dev *vxlan, | 392 | static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, |
393 | struct vxlan_fdb *fdb, int type) | 393 | struct vxlan_rdst *rd, int type) |
394 | { | 394 | { |
395 | struct net *net = dev_net(vxlan->dev); | 395 | struct net *net = dev_net(vxlan->dev); |
396 | struct sk_buff *skb; | 396 | struct sk_buff *skb; |
@@ -400,8 +400,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, | |||
400 | if (skb == NULL) | 400 | if (skb == NULL) |
401 | goto errout; | 401 | goto errout; |
402 | 402 | ||
403 | err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, | 403 | err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); |
404 | first_remote_rtnl(fdb)); | ||
405 | if (err < 0) { | 404 | if (err < 0) { |
406 | /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ | 405 | /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ |
407 | WARN_ON(err == -EMSGSIZE); | 406 | WARN_ON(err == -EMSGSIZE); |
@@ -427,10 +426,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) | |||
427 | .remote_vni = VXLAN_N_VID, | 426 | .remote_vni = VXLAN_N_VID, |
428 | }; | 427 | }; |
429 | 428 | ||
430 | INIT_LIST_HEAD(&f.remotes); | 429 | vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); |
431 | list_add_rcu(&remote.list, &f.remotes); | ||
432 | |||
433 | vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); | ||
434 | } | 430 | } |
435 | 431 | ||
436 | static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) | 432 | static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) |
@@ -438,11 +434,11 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) | |||
438 | struct vxlan_fdb f = { | 434 | struct vxlan_fdb f = { |
439 | .state = NUD_STALE, | 435 | .state = NUD_STALE, |
440 | }; | 436 | }; |
437 | struct vxlan_rdst remote = { }; | ||
441 | 438 | ||
442 | INIT_LIST_HEAD(&f.remotes); | ||
443 | memcpy(f.eth_addr, eth_addr, ETH_ALEN); | 439 | memcpy(f.eth_addr, eth_addr, ETH_ALEN); |
444 | 440 | ||
445 | vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); | 441 | vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); |
446 | } | 442 | } |
447 | 443 | ||
448 | /* Hash Ethernet address */ | 444 | /* Hash Ethernet address */ |
@@ -533,7 +529,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f, | |||
533 | 529 | ||
534 | /* Add/update destinations for multicast */ | 530 | /* Add/update destinations for multicast */ |
535 | static int vxlan_fdb_append(struct vxlan_fdb *f, | 531 | static int vxlan_fdb_append(struct vxlan_fdb *f, |
536 | union vxlan_addr *ip, __be16 port, __u32 vni, __u32 ifindex) | 532 | union vxlan_addr *ip, __be16 port, __u32 vni, |
533 | __u32 ifindex, struct vxlan_rdst **rdp) | ||
537 | { | 534 | { |
538 | struct vxlan_rdst *rd; | 535 | struct vxlan_rdst *rd; |
539 | 536 | ||
@@ -551,6 +548,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, | |||
551 | 548 | ||
552 | list_add_tail_rcu(&rd->list, &f->remotes); | 549 | list_add_tail_rcu(&rd->list, &f->remotes); |
553 | 550 | ||
551 | *rdp = rd; | ||
554 | return 1; | 552 | return 1; |
555 | } | 553 | } |
556 | 554 | ||
@@ -690,6 +688,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, | |||
690 | __be16 port, __u32 vni, __u32 ifindex, | 688 | __be16 port, __u32 vni, __u32 ifindex, |
691 | __u8 ndm_flags) | 689 | __u8 ndm_flags) |
692 | { | 690 | { |
691 | struct vxlan_rdst *rd = NULL; | ||
693 | struct vxlan_fdb *f; | 692 | struct vxlan_fdb *f; |
694 | int notify = 0; | 693 | int notify = 0; |
695 | 694 | ||
@@ -726,7 +725,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, | |||
726 | if ((flags & NLM_F_APPEND) && | 725 | if ((flags & NLM_F_APPEND) && |
727 | (is_multicast_ether_addr(f->eth_addr) || | 726 | (is_multicast_ether_addr(f->eth_addr) || |
728 | is_zero_ether_addr(f->eth_addr))) { | 727 | is_zero_ether_addr(f->eth_addr))) { |
729 | int rc = vxlan_fdb_append(f, ip, port, vni, ifindex); | 728 | int rc = vxlan_fdb_append(f, ip, port, vni, ifindex, |
729 | &rd); | ||
730 | 730 | ||
731 | if (rc < 0) | 731 | if (rc < 0) |
732 | return rc; | 732 | return rc; |
@@ -756,15 +756,18 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, | |||
756 | INIT_LIST_HEAD(&f->remotes); | 756 | INIT_LIST_HEAD(&f->remotes); |
757 | memcpy(f->eth_addr, mac, ETH_ALEN); | 757 | memcpy(f->eth_addr, mac, ETH_ALEN); |
758 | 758 | ||
759 | vxlan_fdb_append(f, ip, port, vni, ifindex); | 759 | vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); |
760 | 760 | ||
761 | ++vxlan->addrcnt; | 761 | ++vxlan->addrcnt; |
762 | hlist_add_head_rcu(&f->hlist, | 762 | hlist_add_head_rcu(&f->hlist, |
763 | vxlan_fdb_head(vxlan, mac)); | 763 | vxlan_fdb_head(vxlan, mac)); |
764 | } | 764 | } |
765 | 765 | ||
766 | if (notify) | 766 | if (notify) { |
767 | vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); | 767 | if (rd == NULL) |
768 | rd = first_remote_rtnl(f); | ||
769 | vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH); | ||
770 | } | ||
768 | 771 | ||
769 | return 0; | 772 | return 0; |
770 | } | 773 | } |
@@ -785,7 +788,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) | |||
785 | "delete %pM\n", f->eth_addr); | 788 | "delete %pM\n", f->eth_addr); |
786 | 789 | ||
787 | --vxlan->addrcnt; | 790 | --vxlan->addrcnt; |
788 | vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH); | 791 | vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_DELNEIGH); |
789 | 792 | ||
790 | hlist_del_rcu(&f->hlist); | 793 | hlist_del_rcu(&f->hlist); |
791 | call_rcu(&f->rcu, vxlan_fdb_free); | 794 | call_rcu(&f->rcu, vxlan_fdb_free); |
@@ -919,6 +922,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], | |||
919 | */ | 922 | */ |
920 | if (rd && !list_is_singular(&f->remotes)) { | 923 | if (rd && !list_is_singular(&f->remotes)) { |
921 | list_del_rcu(&rd->list); | 924 | list_del_rcu(&rd->list); |
925 | vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); | ||
922 | kfree_rcu(rd, rcu); | 926 | kfree_rcu(rd, rcu); |
923 | goto out; | 927 | goto out; |
924 | } | 928 | } |
@@ -993,7 +997,7 @@ static bool vxlan_snoop(struct net_device *dev, | |||
993 | 997 | ||
994 | rdst->remote_ip = *src_ip; | 998 | rdst->remote_ip = *src_ip; |
995 | f->updated = jiffies; | 999 | f->updated = jiffies; |
996 | vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); | 1000 | vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH); |
997 | } else { | 1001 | } else { |
998 | /* learned new entry */ | 1002 | /* learned new entry */ |
999 | spin_lock(&vxlan->hash_lock); | 1003 | spin_lock(&vxlan->hash_lock); |
@@ -1755,8 +1759,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
1755 | if (err) | 1759 | if (err) |
1756 | return err; | 1760 | return err; |
1757 | 1761 | ||
1758 | return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, | 1762 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, |
1759 | false); | 1763 | tos, ttl, df, false); |
1760 | } | 1764 | } |
1761 | EXPORT_SYMBOL_GPL(vxlan_xmit_skb); | 1765 | EXPORT_SYMBOL_GPL(vxlan_xmit_skb); |
1762 | 1766 | ||