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

net: make vid as a parameter for ndo_fdb_add/ndo_fdb_del

Do the work of parsing NDA_VLAN directly in rtnetlink code, pass simple
u16 vid to drivers from there.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Andy Gospodarek <gospo@cumulusnetworks.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jiri Pirko and committed by
David S. Miller
f6f6424b 93859b13

+70 -60
+1 -1
drivers/net/ethernet/intel/i40e/i40e_main.c
··· 7536 7536 */ 7537 7537 static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 7538 7538 struct net_device *dev, 7539 - const unsigned char *addr, 7539 + const unsigned char *addr, u16 vid, 7540 7540 u16 flags) 7541 7541 { 7542 7542 struct i40e_netdev_priv *np = netdev_priv(dev);
+2 -2
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
··· 7708 7708 7709 7709 static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 7710 7710 struct net_device *dev, 7711 - const unsigned char *addr, 7711 + const unsigned char *addr, u16 vid, 7712 7712 u16 flags) 7713 7713 { 7714 7714 /* guarantee we can provide a unique filter for the unicast address */ ··· 7717 7717 return -ENOMEM; 7718 7718 } 7719 7719 7720 - return ndo_dflt_fdb_add(ndm, tb, dev, addr, flags); 7720 + return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags); 7721 7721 } 7722 7722 7723 7723 static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
+5 -4
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
··· 376 376 } 377 377 378 378 static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 379 - struct net_device *netdev, const unsigned char *addr) 379 + struct net_device *netdev, 380 + const unsigned char *addr, u16 vid) 380 381 { 381 382 struct qlcnic_adapter *adapter = netdev_priv(netdev); 382 383 int err = -EOPNOTSUPP; 383 384 384 385 if (!adapter->fdb_mac_learn) 385 - return ndo_dflt_fdb_del(ndm, tb, netdev, addr); 386 + return ndo_dflt_fdb_del(ndm, tb, netdev, addr, vid); 386 387 387 388 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) || 388 389 qlcnic_sriov_check(adapter)) { ··· 402 401 403 402 static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 404 403 struct net_device *netdev, 405 - const unsigned char *addr, u16 flags) 404 + const unsigned char *addr, u16 vid, u16 flags) 406 405 { 407 406 struct qlcnic_adapter *adapter = netdev_priv(netdev); 408 407 int err = 0; 409 408 410 409 if (!adapter->fdb_mac_learn) 411 - return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags); 410 + return ndo_dflt_fdb_add(ndm, tb, netdev, addr, vid, flags); 412 411 413 412 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) && 414 413 !qlcnic_sriov_check(adapter)) {
+2 -2
drivers/net/macvlan.c
··· 873 873 874 874 static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 875 875 struct net_device *dev, 876 - const unsigned char *addr, 876 + const unsigned char *addr, u16 vid, 877 877 u16 flags) 878 878 { 879 879 struct macvlan_dev *vlan = netdev_priv(dev); ··· 898 898 899 899 static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 900 900 struct net_device *dev, 901 - const unsigned char *addr) 901 + const unsigned char *addr, u16 vid) 902 902 { 903 903 struct macvlan_dev *vlan = netdev_priv(dev); 904 904 int err = -EINVAL;
+2 -2
drivers/net/vxlan.c
··· 849 849 /* Add static entry (via netlink) */ 850 850 static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 851 851 struct net_device *dev, 852 - const unsigned char *addr, u16 flags) 852 + const unsigned char *addr, u16 vid, u16 flags) 853 853 { 854 854 struct vxlan_dev *vxlan = netdev_priv(dev); 855 855 /* struct net *net = dev_net(vxlan->dev); */ ··· 885 885 /* Delete entry (via netlink) */ 886 886 static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 887 887 struct net_device *dev, 888 - const unsigned char *addr) 888 + const unsigned char *addr, u16 vid) 889 889 { 890 890 struct vxlan_dev *vxlan = netdev_priv(dev); 891 891 struct vxlan_fdb *f;
+5 -3
include/linux/netdevice.h
··· 951 951 * 952 952 * int (*ndo_fdb_add)(struct ndmsg *ndm, struct nlattr *tb[], 953 953 * struct net_device *dev, 954 - * const unsigned char *addr, u16 flags) 954 + * const unsigned char *addr, u16 vid, u16 flags) 955 955 * Adds an FDB entry to dev for addr. 956 956 * int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[], 957 957 * struct net_device *dev, 958 - * const unsigned char *addr) 958 + * const unsigned char *addr, u16 vid) 959 959 * Deletes the FDB entry from dev coresponding to addr. 960 960 * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb, 961 961 * struct net_device *dev, struct net_device *filter_dev, ··· 1128 1128 struct nlattr *tb[], 1129 1129 struct net_device *dev, 1130 1130 const unsigned char *addr, 1131 + u16 vid, 1131 1132 u16 flags); 1132 1133 int (*ndo_fdb_del)(struct ndmsg *ndm, 1133 1134 struct nlattr *tb[], 1134 1135 struct net_device *dev, 1135 - const unsigned char *addr); 1136 + const unsigned char *addr, 1137 + u16 vid); 1136 1138 int (*ndo_fdb_dump)(struct sk_buff *skb, 1137 1139 struct netlink_callback *cb, 1138 1140 struct net_device *dev,
+4 -2
include/linux/rtnetlink.h
··· 94 94 struct nlattr *tb[], 95 95 struct net_device *dev, 96 96 const unsigned char *addr, 97 - u16 flags); 97 + u16 vid, 98 + u16 flags); 98 99 extern int ndo_dflt_fdb_del(struct ndmsg *ndm, 99 100 struct nlattr *tb[], 100 101 struct net_device *dev, 101 - const unsigned char *addr); 102 + const unsigned char *addr, 103 + u16 vid); 102 104 103 105 extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 104 106 struct net_device *dev, u16 mode);
+4 -35
net/bridge/br_fdb.c
··· 805 805 /* Add new permanent fdb entry with RTM_NEWNEIGH */ 806 806 int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 807 807 struct net_device *dev, 808 - const unsigned char *addr, u16 nlh_flags) 808 + const unsigned char *addr, u16 vid, u16 nlh_flags) 809 809 { 810 810 struct net_bridge_port *p; 811 811 int err = 0; 812 812 struct net_port_vlans *pv; 813 - unsigned short vid = VLAN_N_VID; 814 813 815 814 if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) { 816 815 pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state); 817 816 return -EINVAL; 818 - } 819 - 820 - if (tb[NDA_VLAN]) { 821 - if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) { 822 - pr_info("bridge: RTM_NEWNEIGH with invalid vlan\n"); 823 - return -EINVAL; 824 - } 825 - 826 - vid = nla_get_u16(tb[NDA_VLAN]); 827 - 828 - if (!vid || vid >= VLAN_VID_MASK) { 829 - pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", 830 - vid); 831 - return -EINVAL; 832 - } 833 817 } 834 818 835 819 if (is_zero_ether_addr(addr)) { ··· 829 845 } 830 846 831 847 pv = nbp_get_vlan_info(p); 832 - if (vid != VLAN_N_VID) { 848 + if (vid) { 833 849 if (!pv || !test_bit(vid, pv->vlan_bitmap)) { 834 850 pr_info("bridge: RTM_NEWNEIGH with unconfigured " 835 851 "vlan %d on port %s\n", vid, dev->name); ··· 887 903 /* Remove neighbor entry with RTM_DELNEIGH */ 888 904 int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 889 905 struct net_device *dev, 890 - const unsigned char *addr) 906 + const unsigned char *addr, u16 vid) 891 907 { 892 908 struct net_bridge_port *p; 893 909 int err; 894 910 struct net_port_vlans *pv; 895 - unsigned short vid = VLAN_N_VID; 896 911 897 - if (tb[NDA_VLAN]) { 898 - if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) { 899 - pr_info("bridge: RTM_NEWNEIGH with invalid vlan\n"); 900 - return -EINVAL; 901 - } 902 - 903 - vid = nla_get_u16(tb[NDA_VLAN]); 904 - 905 - if (!vid || vid >= VLAN_VID_MASK) { 906 - pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", 907 - vid); 908 - return -EINVAL; 909 - } 910 - } 911 912 p = br_port_get_rtnl(dev); 912 913 if (p == NULL) { 913 914 pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", ··· 901 932 } 902 933 903 934 pv = nbp_get_vlan_info(p); 904 - if (vid != VLAN_N_VID) { 935 + if (vid) { 905 936 if (!pv || !test_bit(vid, pv->vlan_bitmap)) { 906 937 pr_info("bridge: RTM_DELNEIGH with unconfigured " 907 938 "vlan %d on port %s\n", vid, dev->name);
+2 -2
net/bridge/br_private.h
··· 404 404 const unsigned char *addr, u16 vid, bool added_by_user); 405 405 406 406 int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 407 - struct net_device *dev, const unsigned char *addr); 407 + struct net_device *dev, const unsigned char *addr, u16 vid); 408 408 int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, 409 - const unsigned char *addr, u16 nlh_flags); 409 + const unsigned char *addr, u16 vid, u16 nlh_flags); 410 410 int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, 411 411 struct net_device *dev, struct net_device *fdev, int idx); 412 412 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
+43 -7
net/core/rtnetlink.c
··· 36 36 #include <linux/mutex.h> 37 37 #include <linux/if_addr.h> 38 38 #include <linux/if_bridge.h> 39 + #include <linux/if_vlan.h> 39 40 #include <linux/pci.h> 40 41 #include <linux/etherdevice.h> 41 42 ··· 2313 2312 int ndo_dflt_fdb_add(struct ndmsg *ndm, 2314 2313 struct nlattr *tb[], 2315 2314 struct net_device *dev, 2316 - const unsigned char *addr, 2315 + const unsigned char *addr, u16 vid, 2317 2316 u16 flags) 2318 2317 { 2319 2318 int err = -EINVAL; ··· 2339 2338 } 2340 2339 EXPORT_SYMBOL(ndo_dflt_fdb_add); 2341 2340 2341 + static int fdb_vid_parse(struct nlattr *vlan_attr, u16 *p_vid) 2342 + { 2343 + u16 vid = 0; 2344 + 2345 + if (vlan_attr) { 2346 + if (nla_len(vlan_attr) != sizeof(u16)) { 2347 + pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan\n"); 2348 + return -EINVAL; 2349 + } 2350 + 2351 + vid = nla_get_u16(vlan_attr); 2352 + 2353 + if (!vid || vid >= VLAN_VID_MASK) { 2354 + pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan id %d\n", 2355 + vid); 2356 + return -EINVAL; 2357 + } 2358 + } 2359 + *p_vid = vid; 2360 + return 0; 2361 + } 2362 + 2342 2363 static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) 2343 2364 { 2344 2365 struct net *net = sock_net(skb->sk); ··· 2368 2345 struct nlattr *tb[NDA_MAX+1]; 2369 2346 struct net_device *dev; 2370 2347 u8 *addr; 2348 + u16 vid; 2371 2349 int err; 2372 2350 2373 2351 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); ··· 2394 2370 2395 2371 addr = nla_data(tb[NDA_LLADDR]); 2396 2372 2373 + err = fdb_vid_parse(tb[NDA_VLAN], &vid); 2374 + if (err) 2375 + return err; 2376 + 2397 2377 err = -EOPNOTSUPP; 2398 2378 2399 2379 /* Support fdb on master device the net/bridge default case */ ··· 2406 2378 struct net_device *br_dev = netdev_master_upper_dev_get(dev); 2407 2379 const struct net_device_ops *ops = br_dev->netdev_ops; 2408 2380 2409 - err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags); 2381 + err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid, 2382 + nlh->nlmsg_flags); 2410 2383 if (err) 2411 2384 goto out; 2412 2385 else ··· 2418 2389 if ((ndm->ndm_flags & NTF_SELF)) { 2419 2390 if (dev->netdev_ops->ndo_fdb_add) 2420 2391 err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr, 2392 + vid, 2421 2393 nlh->nlmsg_flags); 2422 2394 else 2423 - err = ndo_dflt_fdb_add(ndm, tb, dev, addr, 2395 + err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, 2424 2396 nlh->nlmsg_flags); 2425 2397 2426 2398 if (!err) { ··· 2439 2409 int ndo_dflt_fdb_del(struct ndmsg *ndm, 2440 2410 struct nlattr *tb[], 2441 2411 struct net_device *dev, 2442 - const unsigned char *addr) 2412 + const unsigned char *addr, u16 vid) 2443 2413 { 2444 2414 int err = -EINVAL; 2445 2415 ··· 2468 2438 struct net_device *dev; 2469 2439 int err = -EINVAL; 2470 2440 __u8 *addr; 2441 + u16 vid; 2471 2442 2472 2443 if (!netlink_capable(skb, CAP_NET_ADMIN)) 2473 2444 return -EPERM; ··· 2496 2465 2497 2466 addr = nla_data(tb[NDA_LLADDR]); 2498 2467 2468 + err = fdb_vid_parse(tb[NDA_VLAN], &vid); 2469 + if (err) 2470 + return err; 2471 + 2499 2472 err = -EOPNOTSUPP; 2500 2473 2501 2474 /* Support fdb on master device the net/bridge default case */ ··· 2509 2474 const struct net_device_ops *ops = br_dev->netdev_ops; 2510 2475 2511 2476 if (ops->ndo_fdb_del) 2512 - err = ops->ndo_fdb_del(ndm, tb, dev, addr); 2477 + err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid); 2513 2478 2514 2479 if (err) 2515 2480 goto out; ··· 2520 2485 /* Embedded bridge, macvlan, and any other device support */ 2521 2486 if (ndm->ndm_flags & NTF_SELF) { 2522 2487 if (dev->netdev_ops->ndo_fdb_del) 2523 - err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr); 2488 + err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr, 2489 + vid); 2524 2490 else 2525 - err = ndo_dflt_fdb_del(ndm, tb, dev, addr); 2491 + err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid); 2526 2492 2527 2493 if (!err) { 2528 2494 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);