summaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 3d9bcc957f7d..8869154fad88 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2487,9 +2487,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
2487 vni = tunnel_id_to_key32(info->key.tun_id); 2487 vni = tunnel_id_to_key32(info->key.tun_id);
2488 ifindex = 0; 2488 ifindex = 0;
2489 dst_cache = &info->dst_cache; 2489 dst_cache = &info->dst_cache;
2490 if (info->options_len && 2490 if (info->key.tun_flags & TUNNEL_VXLAN_OPT) {
2491 info->key.tun_flags & TUNNEL_VXLAN_OPT) 2491 if (info->options_len < sizeof(*md))
2492 goto drop;
2492 md = ip_tunnel_info_opts(info); 2493 md = ip_tunnel_info_opts(info);
2494 }
2493 ttl = info->key.ttl; 2495 ttl = info->key.ttl;
2494 tos = info->key.tos; 2496 tos = info->key.tos;
2495 label = info->key.label; 2497 label = info->key.label;
@@ -3566,10 +3568,13 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
3566{ 3568{
3567 struct vxlan_net *vn = net_generic(net, vxlan_net_id); 3569 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
3568 struct vxlan_dev *vxlan = netdev_priv(dev); 3570 struct vxlan_dev *vxlan = netdev_priv(dev);
3571 struct net_device *remote_dev = NULL;
3569 struct vxlan_fdb *f = NULL; 3572 struct vxlan_fdb *f = NULL;
3570 bool unregister = false; 3573 bool unregister = false;
3574 struct vxlan_rdst *dst;
3571 int err; 3575 int err;
3572 3576
3577 dst = &vxlan->default_dst;
3573 err = vxlan_dev_configure(net, dev, conf, false, extack); 3578 err = vxlan_dev_configure(net, dev, conf, false, extack);
3574 if (err) 3579 if (err)
3575 return err; 3580 return err;
@@ -3577,14 +3582,14 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
3577 dev->ethtool_ops = &vxlan_ethtool_ops; 3582 dev->ethtool_ops = &vxlan_ethtool_ops;
3578 3583
3579 /* create an fdb entry for a valid default destination */ 3584 /* create an fdb entry for a valid default destination */
3580 if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { 3585 if (!vxlan_addr_any(&dst->remote_ip)) {
3581 err = vxlan_fdb_create(vxlan, all_zeros_mac, 3586 err = vxlan_fdb_create(vxlan, all_zeros_mac,
3582 &vxlan->default_dst.remote_ip, 3587 &dst->remote_ip,
3583 NUD_REACHABLE | NUD_PERMANENT, 3588 NUD_REACHABLE | NUD_PERMANENT,
3584 vxlan->cfg.dst_port, 3589 vxlan->cfg.dst_port,
3585 vxlan->default_dst.remote_vni, 3590 dst->remote_vni,
3586 vxlan->default_dst.remote_vni, 3591 dst->remote_vni,
3587 vxlan->default_dst.remote_ifindex, 3592 dst->remote_ifindex,
3588 NTF_SELF, &f); 3593 NTF_SELF, &f);
3589 if (err) 3594 if (err)
3590 return err; 3595 return err;
@@ -3595,26 +3600,41 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
3595 goto errout; 3600 goto errout;
3596 unregister = true; 3601 unregister = true;
3597 3602
3603 if (dst->remote_ifindex) {
3604 remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
3605 if (!remote_dev)
3606 goto errout;
3607
3608 err = netdev_upper_dev_link(remote_dev, dev, extack);
3609 if (err)
3610 goto errout;
3611 }
3612
3598 err = rtnl_configure_link(dev, NULL); 3613 err = rtnl_configure_link(dev, NULL);
3599 if (err) 3614 if (err)
3600 goto errout; 3615 goto unlink;
3601 3616
3602 if (f) { 3617 if (f) {
3603 vxlan_fdb_insert(vxlan, all_zeros_mac, 3618 vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f);
3604 vxlan->default_dst.remote_vni, f);
3605 3619
3606 /* notify default fdb entry */ 3620 /* notify default fdb entry */
3607 err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), 3621 err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
3608 RTM_NEWNEIGH, true, extack); 3622 RTM_NEWNEIGH, true, extack);
3609 if (err) { 3623 if (err) {
3610 vxlan_fdb_destroy(vxlan, f, false, false); 3624 vxlan_fdb_destroy(vxlan, f, false, false);
3625 if (remote_dev)
3626 netdev_upper_dev_unlink(remote_dev, dev);
3611 goto unregister; 3627 goto unregister;
3612 } 3628 }
3613 } 3629 }
3614 3630
3615 list_add(&vxlan->next, &vn->vxlan_list); 3631 list_add(&vxlan->next, &vn->vxlan_list);
3632 if (remote_dev)
3633 dst->remote_dev = remote_dev;
3616 return 0; 3634 return 0;
3617 3635unlink:
3636 if (remote_dev)
3637 netdev_upper_dev_unlink(remote_dev, dev);
3618errout: 3638errout:
3619 /* unregister_netdevice() destroys the default FDB entry with deletion 3639 /* unregister_netdevice() destroys the default FDB entry with deletion
3620 * notification. But the addition notification was not sent yet, so 3640 * notification. But the addition notification was not sent yet, so
@@ -3932,11 +3952,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3932 struct netlink_ext_ack *extack) 3952 struct netlink_ext_ack *extack)
3933{ 3953{
3934 struct vxlan_dev *vxlan = netdev_priv(dev); 3954 struct vxlan_dev *vxlan = netdev_priv(dev);
3935 struct vxlan_rdst *dst = &vxlan->default_dst;
3936 struct net_device *lowerdev; 3955 struct net_device *lowerdev;
3937 struct vxlan_config conf; 3956 struct vxlan_config conf;
3957 struct vxlan_rdst *dst;
3938 int err; 3958 int err;
3939 3959
3960 dst = &vxlan->default_dst;
3940 err = vxlan_nl2conf(tb, data, dev, &conf, true, extack); 3961 err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
3941 if (err) 3962 if (err)
3942 return err; 3963 return err;
@@ -3946,6 +3967,14 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3946 if (err) 3967 if (err)
3947 return err; 3968 return err;
3948 3969
3970 if (dst->remote_dev == lowerdev)
3971 lowerdev = NULL;
3972
3973 err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev,
3974 extack);
3975 if (err)
3976 return err;
3977
3949 /* handle default dst entry */ 3978 /* handle default dst entry */
3950 if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { 3979 if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
3951 u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); 3980 u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
@@ -3962,6 +3991,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3962 NTF_SELF, true, extack); 3991 NTF_SELF, true, extack);
3963 if (err) { 3992 if (err) {
3964 spin_unlock_bh(&vxlan->hash_lock[hash_index]); 3993 spin_unlock_bh(&vxlan->hash_lock[hash_index]);
3994 netdev_adjacent_change_abort(dst->remote_dev,
3995 lowerdev, dev);
3965 return err; 3996 return err;
3966 } 3997 }
3967 } 3998 }
@@ -3979,6 +4010,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3979 if (conf.age_interval != vxlan->cfg.age_interval) 4010 if (conf.age_interval != vxlan->cfg.age_interval)
3980 mod_timer(&vxlan->age_timer, jiffies); 4011 mod_timer(&vxlan->age_timer, jiffies);
3981 4012
4013 netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);
4014 if (lowerdev && lowerdev != dst->remote_dev) {
4015 dst->remote_dev = lowerdev;
4016 netdev_update_lockdep_key(lowerdev);
4017 }
3982 vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); 4018 vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
3983 return 0; 4019 return 0;
3984} 4020}
@@ -3991,6 +4027,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
3991 4027
3992 list_del(&vxlan->next); 4028 list_del(&vxlan->next);
3993 unregister_netdevice_queue(dev, head); 4029 unregister_netdevice_queue(dev, head);
4030 if (vxlan->default_dst.remote_dev)
4031 netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
3994} 4032}
3995 4033
3996static size_t vxlan_get_size(const struct net_device *dev) 4034static size_t vxlan_get_size(const struct net_device *dev)