Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mlxsw: spectrum: Enable VxLAN enslavement to VLAN-aware bridges

Commit 1c30d1836aeb ("mlxsw: spectrum: Enable VxLAN enslavement to
bridges") enabled the enslavement of VxLAN devices to bridges that have
mlxsw ports (or their upper) as slaves. This patch extends mlxsw to also
support VLAN-aware bridges.

The patch is similar in nature to mentioned commit, but there is one
major difference. With VLAN-aware bridges, the VxLAN device's VNI is
mapped to the VLAN that is configured as PVID and egress untagged on the
bridge port.

Therefore, the driver is extended to listen to VLAN configuration on
VxLAN devices of interest and enable / disable NVE encapsulation on the
corresponding 802.1Q FIDs.

To prevent ambiguity, the driver makes sure that a given VLAN is not
configured as PVID and egress untagged on multiple VxLAN devices. This
sanitization takes place both when a port is enslaved to a bridge with
existing VxLAN devices and when a VLAN is added to / removed from a
VxLAN device of interest.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
d70e42b2 48fde466

+404 -14
+41 -4
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
··· 4782 4782 return num_vxlans > 1; 4783 4783 } 4784 4784 4785 + static bool mlxsw_sp_bridge_vxlan_vlan_is_valid(struct net_device *br_dev) 4786 + { 4787 + DECLARE_BITMAP(vlans, VLAN_N_VID) = {0}; 4788 + struct net_device *dev; 4789 + struct list_head *iter; 4790 + 4791 + netdev_for_each_lower_dev(br_dev, dev, iter) { 4792 + u16 pvid; 4793 + int err; 4794 + 4795 + if (!netif_is_vxlan(dev)) 4796 + continue; 4797 + 4798 + err = mlxsw_sp_vxlan_mapped_vid(dev, &pvid); 4799 + if (err || !pvid) 4800 + continue; 4801 + 4802 + if (test_and_set_bit(pvid, vlans)) 4803 + return false; 4804 + } 4805 + 4806 + return true; 4807 + } 4808 + 4785 4809 static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev, 4786 4810 struct netlink_ext_ack *extack) 4787 4811 { ··· 4814 4790 return false; 4815 4791 } 4816 4792 4817 - if (br_vlan_enabled(br_dev)) { 4818 - NL_SET_ERR_MSG_MOD(extack, "VLAN filtering can not be enabled on a bridge with a VxLAN device"); 4793 + if (!br_vlan_enabled(br_dev) && 4794 + mlxsw_sp_bridge_has_multiple_vxlans(br_dev)) { 4795 + NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices are not supported in a VLAN-unaware bridge"); 4819 4796 return false; 4820 4797 } 4821 4798 4822 - if (mlxsw_sp_bridge_has_multiple_vxlans(br_dev)) { 4823 - NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices are not supported in a VLAN-unaware bridge"); 4799 + if (br_vlan_enabled(br_dev) && 4800 + !mlxsw_sp_bridge_vxlan_vlan_is_valid(br_dev)) { 4801 + NL_SET_ERR_MSG_MOD(extack, "Multiple VxLAN devices cannot have the same VLAN as PVID and egress untagged"); 4824 4802 return false; 4825 4803 } 4826 4804 ··· 5197 5171 if (cu_info->linking) { 5198 5172 if (!netif_running(dev)) 5199 5173 return 0; 5174 + /* When the bridge is VLAN-aware, the VNI of the VxLAN 5175 + * device needs to be mapped to a VLAN, but at this 5176 + * point no VLANs are configured on the VxLAN device 5177 + */ 5178 + if (br_vlan_enabled(upper_dev)) 5179 + return 0; 5200 5180 return mlxsw_sp_bridge_vxlan_join(mlxsw_sp, upper_dev, 5201 5181 dev, 0, extack); 5202 5182 } else { 5183 + /* VLANs were already flushed, which triggered the 5184 + * necessary cleanup 5185 + */ 5186 + if (br_vlan_enabled(upper_dev)) 5187 + return 0; 5203 5188 mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, dev); 5204 5189 } 5205 5190 break;
+21
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
··· 8 8 #include <linux/netdevice.h> 9 9 #include <linux/rhashtable.h> 10 10 #include <linux/bitops.h> 11 + #include <linux/if_bridge.h> 11 12 #include <linux/if_vlan.h> 12 13 #include <linux/list.h> 13 14 #include <linux/dcbnl.h> ··· 260 259 static inline bool mlxsw_sp_bridge_has_vxlan(struct net_device *br_dev) 261 260 { 262 261 return !!mlxsw_sp_bridge_vxlan_dev_find(br_dev); 262 + } 263 + 264 + static inline int 265 + mlxsw_sp_vxlan_mapped_vid(const struct net_device *vxlan_dev, u16 *p_vid) 266 + { 267 + struct bridge_vlan_info vinfo; 268 + u16 vid = 0; 269 + int err; 270 + 271 + err = br_vlan_get_pvid(vxlan_dev, &vid); 272 + if (err || !vid) 273 + goto out; 274 + 275 + err = br_vlan_get_info(vxlan_dev, vid, &vinfo); 276 + if (err || !(vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED)) 277 + vid = 0; 278 + 279 + out: 280 + *p_vid = vid; 281 + return err; 263 282 } 264 283 265 284 static inline bool
+342 -10
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
··· 2006 2006 const struct net_device *vxlan_dev, u16 vid, 2007 2007 struct netlink_ext_ack *extack) 2008 2008 { 2009 - WARN_ON(1); 2010 - return -EINVAL; 2009 + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev); 2010 + struct vxlan_dev *vxlan = netdev_priv(vxlan_dev); 2011 + struct mlxsw_sp_nve_params params = { 2012 + .type = MLXSW_SP_NVE_TYPE_VXLAN, 2013 + .vni = vxlan->cfg.vni, 2014 + .dev = vxlan_dev, 2015 + }; 2016 + struct mlxsw_sp_fid *fid; 2017 + int err; 2018 + 2019 + /* If the VLAN is 0, we need to find the VLAN that is configured as 2020 + * PVID and egress untagged on the bridge port of the VxLAN device. 2021 + * It is possible no such VLAN exists 2022 + */ 2023 + if (!vid) { 2024 + err = mlxsw_sp_vxlan_mapped_vid(vxlan_dev, &vid); 2025 + if (err || !vid) 2026 + return err; 2027 + } 2028 + 2029 + /* If no other port is member in the VLAN, then the FID does not exist. 2030 + * NVE will be enabled on the FID once a port joins the VLAN 2031 + */ 2032 + fid = mlxsw_sp_fid_8021q_lookup(mlxsw_sp, vid); 2033 + if (!fid) 2034 + return 0; 2035 + 2036 + if (mlxsw_sp_fid_vni_is_set(fid)) { 2037 + err = -EINVAL; 2038 + goto err_vni_exists; 2039 + } 2040 + 2041 + err = mlxsw_sp_nve_fid_enable(mlxsw_sp, fid, &params, extack); 2042 + if (err) 2043 + goto err_nve_fid_enable; 2044 + 2045 + /* The tunnel port does not hold a reference on the FID. Only 2046 + * local ports and the router port 2047 + */ 2048 + mlxsw_sp_fid_put(fid); 2049 + 2050 + return 0; 2051 + 2052 + err_nve_fid_enable: 2053 + err_vni_exists: 2054 + mlxsw_sp_fid_put(fid); 2055 + return err; 2056 + } 2057 + 2058 + static struct net_device * 2059 + mlxsw_sp_bridge_8021q_vxlan_dev_find(struct net_device *br_dev, u16 vid) 2060 + { 2061 + struct net_device *dev; 2062 + struct list_head *iter; 2063 + 2064 + netdev_for_each_lower_dev(br_dev, dev, iter) { 2065 + u16 pvid; 2066 + int err; 2067 + 2068 + if (!netif_is_vxlan(dev)) 2069 + continue; 2070 + 2071 + err = mlxsw_sp_vxlan_mapped_vid(dev, &pvid); 2072 + if (err || pvid != vid) 2073 + continue; 2074 + 2075 + return dev; 2076 + } 2077 + 2078 + return NULL; 2011 2079 } 2012 2080 2013 2081 static struct mlxsw_sp_fid * ··· 2083 2015 u16 vid) 2084 2016 { 2085 2017 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev); 2018 + struct net_device *vxlan_dev; 2019 + struct mlxsw_sp_fid *fid; 2020 + int err; 2086 2021 2087 - return mlxsw_sp_fid_8021q_get(mlxsw_sp, vid); 2022 + fid = mlxsw_sp_fid_8021q_get(mlxsw_sp, vid); 2023 + if (IS_ERR(fid)) 2024 + return fid; 2025 + 2026 + if (mlxsw_sp_fid_vni_is_set(fid)) 2027 + return fid; 2028 + 2029 + /* Find the VxLAN device that has the specified VLAN configured as 2030 + * PVID and egress untagged. There can be at most one such device 2031 + */ 2032 + vxlan_dev = mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, 2033 + vid); 2034 + if (!vxlan_dev) 2035 + return fid; 2036 + 2037 + if (!netif_running(vxlan_dev)) 2038 + return fid; 2039 + 2040 + err = mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, vxlan_dev, vid, 2041 + NULL); 2042 + if (err) 2043 + goto err_vxlan_join; 2044 + 2045 + return fid; 2046 + 2047 + err_vxlan_join: 2048 + mlxsw_sp_fid_put(fid); 2049 + return ERR_PTR(err); 2088 2050 } 2089 2051 2090 2052 static struct mlxsw_sp_fid * ··· 3190 3092 .notifier_call = mlxsw_sp_switchdev_event, 3191 3093 }; 3192 3094 3095 + static int 3096 + mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp, 3097 + struct mlxsw_sp_bridge_device *bridge_device, 3098 + const struct net_device *vxlan_dev, u16 vid, 3099 + bool flag_untagged, bool flag_pvid, 3100 + struct switchdev_trans *trans) 3101 + { 3102 + struct vxlan_dev *vxlan = netdev_priv(vxlan_dev); 3103 + __be32 vni = vxlan->cfg.vni; 3104 + struct mlxsw_sp_fid *fid; 3105 + u16 old_vid; 3106 + int err; 3107 + 3108 + /* We cannot have the same VLAN as PVID and egress untagged on multiple 3109 + * VxLAN devices. Note that we get this notification before the VLAN is 3110 + * actually added to the bridge's database, so it is not possible for 3111 + * the lookup function to return 'vxlan_dev' 3112 + */ 3113 + if (flag_untagged && flag_pvid && 3114 + mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) 3115 + return -EINVAL; 3116 + 3117 + if (switchdev_trans_ph_prepare(trans)) 3118 + return 0; 3119 + 3120 + if (!netif_running(vxlan_dev)) 3121 + return 0; 3122 + 3123 + /* First case: FID is not associated with this VNI, but the new VLAN 3124 + * is both PVID and egress untagged. Need to enable NVE on the FID, if 3125 + * it exists 3126 + */ 3127 + fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vni); 3128 + if (!fid) { 3129 + if (!flag_untagged || !flag_pvid) 3130 + return 0; 3131 + return mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, 3132 + vxlan_dev, vid, NULL); 3133 + } 3134 + 3135 + /* Second case: FID is associated with the VNI and the VLAN associated 3136 + * with the FID is the same as the notified VLAN. This means the flags 3137 + * (PVID / egress untagged) were toggled and that NVE should be 3138 + * disabled on the FID 3139 + */ 3140 + old_vid = mlxsw_sp_fid_8021q_vid(fid); 3141 + if (vid == old_vid) { 3142 + if (WARN_ON(flag_untagged && flag_pvid)) { 3143 + mlxsw_sp_fid_put(fid); 3144 + return -EINVAL; 3145 + } 3146 + mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev); 3147 + mlxsw_sp_fid_put(fid); 3148 + return 0; 3149 + } 3150 + 3151 + /* Third case: A new VLAN was configured on the VxLAN device, but this 3152 + * VLAN is not PVID, so there is nothing to do. 3153 + */ 3154 + if (!flag_pvid) { 3155 + mlxsw_sp_fid_put(fid); 3156 + return 0; 3157 + } 3158 + 3159 + /* Fourth case: Thew new VLAN is PVID, which means the VLAN currently 3160 + * mapped to the VNI should be unmapped 3161 + */ 3162 + mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev); 3163 + mlxsw_sp_fid_put(fid); 3164 + 3165 + /* Fifth case: The new VLAN is also egress untagged, which means the 3166 + * VLAN needs to be mapped to the VNI 3167 + */ 3168 + if (!flag_untagged) 3169 + return 0; 3170 + 3171 + err = mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, vxlan_dev, vid, 3172 + NULL); 3173 + if (err) 3174 + goto err_vxlan_join; 3175 + 3176 + return 0; 3177 + 3178 + err_vxlan_join: 3179 + mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, vxlan_dev, old_vid, 3180 + NULL); 3181 + return err; 3182 + } 3183 + 3184 + static void 3185 + mlxsw_sp_switchdev_vxlan_vlan_del(struct mlxsw_sp *mlxsw_sp, 3186 + struct mlxsw_sp_bridge_device *bridge_device, 3187 + const struct net_device *vxlan_dev, u16 vid) 3188 + { 3189 + struct vxlan_dev *vxlan = netdev_priv(vxlan_dev); 3190 + __be32 vni = vxlan->cfg.vni; 3191 + struct mlxsw_sp_fid *fid; 3192 + 3193 + if (!netif_running(vxlan_dev)) 3194 + return; 3195 + 3196 + fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vni); 3197 + if (!fid) 3198 + return; 3199 + 3200 + /* A different VLAN than the one mapped to the VNI is deleted */ 3201 + if (mlxsw_sp_fid_8021q_vid(fid) != vid) 3202 + goto out; 3203 + 3204 + mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev); 3205 + 3206 + out: 3207 + mlxsw_sp_fid_put(fid); 3208 + } 3209 + 3210 + static int 3211 + mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev, 3212 + struct switchdev_notifier_port_obj_info * 3213 + port_obj_info) 3214 + { 3215 + struct switchdev_obj_port_vlan *vlan = 3216 + SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj); 3217 + bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 3218 + bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 3219 + struct switchdev_trans *trans = port_obj_info->trans; 3220 + struct mlxsw_sp_bridge_device *bridge_device; 3221 + struct mlxsw_sp *mlxsw_sp; 3222 + struct net_device *br_dev; 3223 + u16 vid; 3224 + 3225 + br_dev = netdev_master_upper_dev_get(vxlan_dev); 3226 + if (!br_dev) 3227 + return 0; 3228 + 3229 + mlxsw_sp = mlxsw_sp_lower_get(br_dev); 3230 + if (!mlxsw_sp) 3231 + return 0; 3232 + 3233 + port_obj_info->handled = true; 3234 + 3235 + bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev); 3236 + if (!bridge_device) 3237 + return -EINVAL; 3238 + 3239 + if (!bridge_device->vlan_enabled) 3240 + return 0; 3241 + 3242 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 3243 + int err; 3244 + 3245 + err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device, 3246 + vxlan_dev, vid, 3247 + flag_untagged, 3248 + flag_pvid, trans); 3249 + if (err) 3250 + return err; 3251 + } 3252 + 3253 + return 0; 3254 + } 3255 + 3256 + static void 3257 + mlxsw_sp_switchdev_vxlan_vlans_del(struct net_device *vxlan_dev, 3258 + struct switchdev_notifier_port_obj_info * 3259 + port_obj_info) 3260 + { 3261 + struct switchdev_obj_port_vlan *vlan = 3262 + SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj); 3263 + struct mlxsw_sp_bridge_device *bridge_device; 3264 + struct mlxsw_sp *mlxsw_sp; 3265 + struct net_device *br_dev; 3266 + u16 vid; 3267 + 3268 + br_dev = netdev_master_upper_dev_get(vxlan_dev); 3269 + if (!br_dev) 3270 + return; 3271 + 3272 + mlxsw_sp = mlxsw_sp_lower_get(br_dev); 3273 + if (!mlxsw_sp) 3274 + return; 3275 + 3276 + port_obj_info->handled = true; 3277 + 3278 + bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev); 3279 + if (!bridge_device) 3280 + return; 3281 + 3282 + if (!bridge_device->vlan_enabled) 3283 + return; 3284 + 3285 + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) 3286 + mlxsw_sp_switchdev_vxlan_vlan_del(mlxsw_sp, bridge_device, 3287 + vxlan_dev, vid); 3288 + } 3289 + 3290 + static int 3291 + mlxsw_sp_switchdev_handle_vxlan_obj_add(struct net_device *vxlan_dev, 3292 + struct switchdev_notifier_port_obj_info * 3293 + port_obj_info) 3294 + { 3295 + int err = 0; 3296 + 3297 + switch (port_obj_info->obj->id) { 3298 + case SWITCHDEV_OBJ_ID_PORT_VLAN: 3299 + err = mlxsw_sp_switchdev_vxlan_vlans_add(vxlan_dev, 3300 + port_obj_info); 3301 + break; 3302 + default: 3303 + break; 3304 + } 3305 + 3306 + return err; 3307 + } 3308 + 3309 + static void 3310 + mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev, 3311 + struct switchdev_notifier_port_obj_info * 3312 + port_obj_info) 3313 + { 3314 + switch (port_obj_info->obj->id) { 3315 + case SWITCHDEV_OBJ_ID_PORT_VLAN: 3316 + mlxsw_sp_switchdev_vxlan_vlans_del(vxlan_dev, port_obj_info); 3317 + break; 3318 + default: 3319 + break; 3320 + } 3321 + } 3322 + 3193 3323 static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused, 3194 3324 unsigned long event, void *ptr) 3195 3325 { 3196 3326 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 3197 - int err; 3327 + int err = 0; 3198 3328 3199 3329 switch (event) { 3200 3330 case SWITCHDEV_PORT_OBJ_ADD: 3201 - err = switchdev_handle_port_obj_add(dev, ptr, 3202 - mlxsw_sp_port_dev_check, 3203 - mlxsw_sp_port_obj_add); 3331 + if (netif_is_vxlan(dev)) 3332 + err = mlxsw_sp_switchdev_handle_vxlan_obj_add(dev, ptr); 3333 + else 3334 + err = switchdev_handle_port_obj_add(dev, ptr, 3335 + mlxsw_sp_port_dev_check, 3336 + mlxsw_sp_port_obj_add); 3204 3337 return notifier_from_errno(err); 3205 3338 case SWITCHDEV_PORT_OBJ_DEL: 3206 - err = switchdev_handle_port_obj_del(dev, ptr, 3207 - mlxsw_sp_port_dev_check, 3208 - mlxsw_sp_port_obj_del); 3339 + if (netif_is_vxlan(dev)) 3340 + mlxsw_sp_switchdev_handle_vxlan_obj_del(dev, ptr); 3341 + else 3342 + err = switchdev_handle_port_obj_del(dev, ptr, 3343 + mlxsw_sp_port_dev_check, 3344 + mlxsw_sp_port_obj_del); 3209 3345 return notifier_from_errno(err); 3210 3346 } 3211 3347