diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 62 |
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 | 3635 | unlink: | |
3636 | if (remote_dev) | ||
3637 | netdev_upper_dev_unlink(remote_dev, dev); | ||
3618 | errout: | 3638 | errout: |
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 | ||
3996 | static size_t vxlan_get_size(const struct net_device *dev) | 4034 | static size_t vxlan_get_size(const struct net_device *dev) |