aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c9
-rw-r--r--drivers/net/macvlan.c4
-rw-r--r--drivers/net/vxlan.c4
-rw-r--r--include/linux/netdevice.h8
-rw-r--r--include/linux/rtnetlink.h6
-rw-r--r--net/bridge/br_fdb.c39
-rw-r--r--net/bridge/br_private.h4
-rw-r--r--net/core/rtnetlink.c50
10 files changed, 70 insertions, 60 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 7262077ad547..5ed5e4036dd9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7536,7 +7536,7 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
7536 */ 7536 */
7537static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 7537static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
7538 struct net_device *dev, 7538 struct net_device *dev,
7539 const unsigned char *addr, 7539 const unsigned char *addr, u16 vid,
7540 u16 flags) 7540 u16 flags)
7541{ 7541{
7542 struct i40e_netdev_priv *np = netdev_priv(dev); 7542 struct i40e_netdev_priv *np = netdev_priv(dev);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 52776f9e1f71..74aadeb56ada 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7708,7 +7708,7 @@ static int ixgbe_set_features(struct net_device *netdev,
7708 7708
7709static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 7709static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
7710 struct net_device *dev, 7710 struct net_device *dev,
7711 const unsigned char *addr, 7711 const unsigned char *addr, u16 vid,
7712 u16 flags) 7712 u16 flags)
7713{ 7713{
7714 /* guarantee we can provide a unique filter for the unicast address */ 7714 /* guarantee we can provide a unique filter for the unicast address */
@@ -7717,7 +7717,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
7717 return -ENOMEM; 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
7723static int ixgbe_ndo_bridge_setlink(struct net_device *dev, 7723static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index a913b3ad2f89..3227c8063edd 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -376,13 +376,14 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
376} 376}
377 377
378static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 378static 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 struct qlcnic_adapter *adapter = netdev_priv(netdev); 382 struct qlcnic_adapter *adapter = netdev_priv(netdev);
382 int err = -EOPNOTSUPP; 383 int err = -EOPNOTSUPP;
383 384
384 if (!adapter->fdb_mac_learn) 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 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) || 388 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
388 qlcnic_sriov_check(adapter)) { 389 qlcnic_sriov_check(adapter)) {
@@ -401,13 +402,13 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
401 402
402static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 403static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
403 struct net_device *netdev, 404 struct net_device *netdev,
404 const unsigned char *addr, u16 flags) 405 const unsigned char *addr, u16 vid, u16 flags)
405{ 406{
406 struct qlcnic_adapter *adapter = netdev_priv(netdev); 407 struct qlcnic_adapter *adapter = netdev_priv(netdev);
407 int err = 0; 408 int err = 0;
408 409
409 if (!adapter->fdb_mac_learn) 410 if (!adapter->fdb_mac_learn)
410 return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags); 411 return ndo_dflt_fdb_add(ndm, tb, netdev, addr, vid, flags);
411 412
412 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) && 413 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) &&
413 !qlcnic_sriov_check(adapter)) { 414 !qlcnic_sriov_check(adapter)) {
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 11d4b3506d6e..9538674587aa 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -873,7 +873,7 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
873 873
874static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 874static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
875 struct net_device *dev, 875 struct net_device *dev,
876 const unsigned char *addr, 876 const unsigned char *addr, u16 vid,
877 u16 flags) 877 u16 flags)
878{ 878{
879 struct macvlan_dev *vlan = netdev_priv(dev); 879 struct macvlan_dev *vlan = netdev_priv(dev);
@@ -898,7 +898,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
898 898
899static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 899static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
900 struct net_device *dev, 900 struct net_device *dev,
901 const unsigned char *addr) 901 const unsigned char *addr, u16 vid)
902{ 902{
903 struct macvlan_dev *vlan = netdev_priv(dev); 903 struct macvlan_dev *vlan = netdev_priv(dev);
904 int err = -EINVAL; 904 int err = -EINVAL;
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index d802a1ae4560..31ecb03368c6 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -849,7 +849,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
849/* Add static entry (via netlink) */ 849/* Add static entry (via netlink) */
850static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 850static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
851 struct net_device *dev, 851 struct net_device *dev,
852 const unsigned char *addr, u16 flags) 852 const unsigned char *addr, u16 vid, u16 flags)
853{ 853{
854 struct vxlan_dev *vxlan = netdev_priv(dev); 854 struct vxlan_dev *vxlan = netdev_priv(dev);
855 /* struct net *net = dev_net(vxlan->dev); */ 855 /* struct net *net = dev_net(vxlan->dev); */
@@ -885,7 +885,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
885/* Delete entry (via netlink) */ 885/* Delete entry (via netlink) */
886static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 886static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
887 struct net_device *dev, 887 struct net_device *dev,
888 const unsigned char *addr) 888 const unsigned char *addr, u16 vid)
889{ 889{
890 struct vxlan_dev *vxlan = netdev_priv(dev); 890 struct vxlan_dev *vxlan = netdev_priv(dev);
891 struct vxlan_fdb *f; 891 struct vxlan_fdb *f;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2cb772495f7a..589929cf4700 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -951,11 +951,11 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
951 * 951 *
952 * int (*ndo_fdb_add)(struct ndmsg *ndm, struct nlattr *tb[], 952 * int (*ndo_fdb_add)(struct ndmsg *ndm, struct nlattr *tb[],
953 * struct net_device *dev, 953 * struct net_device *dev,
954 * const unsigned char *addr, u16 flags) 954 * const unsigned char *addr, u16 vid, u16 flags)
955 * Adds an FDB entry to dev for addr. 955 * Adds an FDB entry to dev for addr.
956 * int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[], 956 * int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[],
957 * struct net_device *dev, 957 * struct net_device *dev,
958 * const unsigned char *addr) 958 * const unsigned char *addr, u16 vid)
959 * Deletes the FDB entry from dev coresponding to addr. 959 * Deletes the FDB entry from dev coresponding to addr.
960 * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb, 960 * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
961 * struct net_device *dev, struct net_device *filter_dev, 961 * struct net_device *dev, struct net_device *filter_dev,
@@ -1128,11 +1128,13 @@ struct net_device_ops {
1128 struct nlattr *tb[], 1128 struct nlattr *tb[],
1129 struct net_device *dev, 1129 struct net_device *dev,
1130 const unsigned char *addr, 1130 const unsigned char *addr,
1131 u16 vid,
1131 u16 flags); 1132 u16 flags);
1132 int (*ndo_fdb_del)(struct ndmsg *ndm, 1133 int (*ndo_fdb_del)(struct ndmsg *ndm,
1133 struct nlattr *tb[], 1134 struct nlattr *tb[],
1134 struct net_device *dev, 1135 struct net_device *dev,
1135 const unsigned char *addr); 1136 const unsigned char *addr,
1137 u16 vid);
1136 int (*ndo_fdb_dump)(struct sk_buff *skb, 1138 int (*ndo_fdb_dump)(struct sk_buff *skb,
1137 struct netlink_callback *cb, 1139 struct netlink_callback *cb,
1138 struct net_device *dev, 1140 struct net_device *dev,
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 6cacbce1a06c..063f0f581fe0 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -94,11 +94,13 @@ extern int ndo_dflt_fdb_add(struct ndmsg *ndm,
94 struct nlattr *tb[], 94 struct nlattr *tb[],
95 struct net_device *dev, 95 struct net_device *dev,
96 const unsigned char *addr, 96 const unsigned char *addr,
97 u16 flags); 97 u16 vid,
98 u16 flags);
98extern int ndo_dflt_fdb_del(struct ndmsg *ndm, 99extern int ndo_dflt_fdb_del(struct ndmsg *ndm,
99 struct nlattr *tb[], 100 struct nlattr *tb[],
100 struct net_device *dev, 101 struct net_device *dev,
101 const unsigned char *addr); 102 const unsigned char *addr,
103 u16 vid);
102 104
103extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 105extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
104 struct net_device *dev, u16 mode); 106 struct net_device *dev, u16 mode);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 08ef4e7a2439..b1be971eb06c 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -805,33 +805,17 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
805/* Add new permanent fdb entry with RTM_NEWNEIGH */ 805/* Add new permanent fdb entry with RTM_NEWNEIGH */
806int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 806int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
807 struct net_device *dev, 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 struct net_bridge_port *p; 810 struct net_bridge_port *p;
811 int err = 0; 811 int err = 0;
812 struct net_port_vlans *pv; 812 struct net_port_vlans *pv;
813 unsigned short vid = VLAN_N_VID;
814 813
815 if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) { 814 if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
816 pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state); 815 pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
817 return -EINVAL; 816 return -EINVAL;
818 } 817 }
819 818
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 }
834
835 if (is_zero_ether_addr(addr)) { 819 if (is_zero_ether_addr(addr)) {
836 pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); 820 pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n");
837 return -EINVAL; 821 return -EINVAL;
@@ -845,7 +829,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
845 } 829 }
846 830
847 pv = nbp_get_vlan_info(p); 831 pv = nbp_get_vlan_info(p);
848 if (vid != VLAN_N_VID) { 832 if (vid) {
849 if (!pv || !test_bit(vid, pv->vlan_bitmap)) { 833 if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
850 pr_info("bridge: RTM_NEWNEIGH with unconfigured " 834 pr_info("bridge: RTM_NEWNEIGH with unconfigured "
851 "vlan %d on port %s\n", vid, dev->name); 835 "vlan %d on port %s\n", vid, dev->name);
@@ -903,27 +887,12 @@ static int __br_fdb_delete(struct net_bridge_port *p,
903/* Remove neighbor entry with RTM_DELNEIGH */ 887/* Remove neighbor entry with RTM_DELNEIGH */
904int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 888int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
905 struct net_device *dev, 889 struct net_device *dev,
906 const unsigned char *addr) 890 const unsigned char *addr, u16 vid)
907{ 891{
908 struct net_bridge_port *p; 892 struct net_bridge_port *p;
909 int err; 893 int err;
910 struct net_port_vlans *pv; 894 struct net_port_vlans *pv;
911 unsigned short vid = VLAN_N_VID;
912
913 if (tb[NDA_VLAN]) {
914 if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
915 pr_info("bridge: RTM_NEWNEIGH with invalid vlan\n");
916 return -EINVAL;
917 }
918 895
919 vid = nla_get_u16(tb[NDA_VLAN]);
920
921 if (!vid || vid >= VLAN_VID_MASK) {
922 pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
923 vid);
924 return -EINVAL;
925 }
926 }
927 p = br_port_get_rtnl(dev); 896 p = br_port_get_rtnl(dev);
928 if (p == NULL) { 897 if (p == NULL) {
929 pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", 898 pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
@@ -932,7 +901,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
932 } 901 }
933 902
934 pv = nbp_get_vlan_info(p); 903 pv = nbp_get_vlan_info(p);
935 if (vid != VLAN_N_VID) { 904 if (vid) {
936 if (!pv || !test_bit(vid, pv->vlan_bitmap)) { 905 if (!pv || !test_bit(vid, pv->vlan_bitmap)) {
937 pr_info("bridge: RTM_DELNEIGH with unconfigured " 906 pr_info("bridge: RTM_DELNEIGH with unconfigured "
938 "vlan %d on port %s\n", vid, dev->name); 907 "vlan %d on port %s\n", vid, dev->name);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 5b370773ad9c..1b529da8234d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -404,9 +404,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
404 const unsigned char *addr, u16 vid, bool added_by_user); 404 const unsigned char *addr, u16 vid, bool added_by_user);
405 405
406int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], 406int 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);
408int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, 408int 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);
410int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, 410int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
411 struct net_device *dev, struct net_device *fdev, int idx); 411 struct net_device *dev, struct net_device *fdev, int idx);
412int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); 412int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b9b7dfaf202b..1a233c1c8ab4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -36,6 +36,7 @@
36#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <linux/if_addr.h> 37#include <linux/if_addr.h>
38#include <linux/if_bridge.h> 38#include <linux/if_bridge.h>
39#include <linux/if_vlan.h>
39#include <linux/pci.h> 40#include <linux/pci.h>
40#include <linux/etherdevice.h> 41#include <linux/etherdevice.h>
41 42
@@ -2312,7 +2313,7 @@ errout:
2312int ndo_dflt_fdb_add(struct ndmsg *ndm, 2313int ndo_dflt_fdb_add(struct ndmsg *ndm,
2313 struct nlattr *tb[], 2314 struct nlattr *tb[],
2314 struct net_device *dev, 2315 struct net_device *dev,
2315 const unsigned char *addr, 2316 const unsigned char *addr, u16 vid,
2316 u16 flags) 2317 u16 flags)
2317{ 2318{
2318 int err = -EINVAL; 2319 int err = -EINVAL;
@@ -2338,6 +2339,28 @@ int ndo_dflt_fdb_add(struct ndmsg *ndm,
2338} 2339}
2339EXPORT_SYMBOL(ndo_dflt_fdb_add); 2340EXPORT_SYMBOL(ndo_dflt_fdb_add);
2340 2341
2342static int fdb_vid_parse(struct nlattr *vlan_attr, u16 *p_vid)
2343{
2344 u16 vid = 0;
2345
2346 if (vlan_attr) {
2347 if (nla_len(vlan_attr) != sizeof(u16)) {
2348 pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan\n");
2349 return -EINVAL;
2350 }
2351
2352 vid = nla_get_u16(vlan_attr);
2353
2354 if (!vid || vid >= VLAN_VID_MASK) {
2355 pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan id %d\n",
2356 vid);
2357 return -EINVAL;
2358 }
2359 }
2360 *p_vid = vid;
2361 return 0;
2362}
2363
2341static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) 2364static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
2342{ 2365{
2343 struct net *net = sock_net(skb->sk); 2366 struct net *net = sock_net(skb->sk);
@@ -2345,6 +2368,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
2345 struct nlattr *tb[NDA_MAX+1]; 2368 struct nlattr *tb[NDA_MAX+1];
2346 struct net_device *dev; 2369 struct net_device *dev;
2347 u8 *addr; 2370 u8 *addr;
2371 u16 vid;
2348 int err; 2372 int err;
2349 2373
2350 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); 2374 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
@@ -2370,6 +2394,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
2370 2394
2371 addr = nla_data(tb[NDA_LLADDR]); 2395 addr = nla_data(tb[NDA_LLADDR]);
2372 2396
2397 err = fdb_vid_parse(tb[NDA_VLAN], &vid);
2398 if (err)
2399 return err;
2400
2373 err = -EOPNOTSUPP; 2401 err = -EOPNOTSUPP;
2374 2402
2375 /* Support fdb on master device the net/bridge default case */ 2403 /* Support fdb on master device the net/bridge default case */
@@ -2378,7 +2406,8 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
2378 struct net_device *br_dev = netdev_master_upper_dev_get(dev); 2406 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2379 const struct net_device_ops *ops = br_dev->netdev_ops; 2407 const struct net_device_ops *ops = br_dev->netdev_ops;
2380 2408
2381 err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags); 2409 err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid,
2410 nlh->nlmsg_flags);
2382 if (err) 2411 if (err)
2383 goto out; 2412 goto out;
2384 else 2413 else
@@ -2389,9 +2418,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
2389 if ((ndm->ndm_flags & NTF_SELF)) { 2418 if ((ndm->ndm_flags & NTF_SELF)) {
2390 if (dev->netdev_ops->ndo_fdb_add) 2419 if (dev->netdev_ops->ndo_fdb_add)
2391 err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr, 2420 err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
2421 vid,
2392 nlh->nlmsg_flags); 2422 nlh->nlmsg_flags);
2393 else 2423 else
2394 err = ndo_dflt_fdb_add(ndm, tb, dev, addr, 2424 err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid,
2395 nlh->nlmsg_flags); 2425 nlh->nlmsg_flags);
2396 2426
2397 if (!err) { 2427 if (!err) {
@@ -2409,7 +2439,7 @@ out:
2409int ndo_dflt_fdb_del(struct ndmsg *ndm, 2439int ndo_dflt_fdb_del(struct ndmsg *ndm,
2410 struct nlattr *tb[], 2440 struct nlattr *tb[],
2411 struct net_device *dev, 2441 struct net_device *dev,
2412 const unsigned char *addr) 2442 const unsigned char *addr, u16 vid)
2413{ 2443{
2414 int err = -EINVAL; 2444 int err = -EINVAL;
2415 2445
@@ -2438,6 +2468,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2438 struct net_device *dev; 2468 struct net_device *dev;
2439 int err = -EINVAL; 2469 int err = -EINVAL;
2440 __u8 *addr; 2470 __u8 *addr;
2471 u16 vid;
2441 2472
2442 if (!netlink_capable(skb, CAP_NET_ADMIN)) 2473 if (!netlink_capable(skb, CAP_NET_ADMIN))
2443 return -EPERM; 2474 return -EPERM;
@@ -2465,6 +2496,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2465 2496
2466 addr = nla_data(tb[NDA_LLADDR]); 2497 addr = nla_data(tb[NDA_LLADDR]);
2467 2498
2499 err = fdb_vid_parse(tb[NDA_VLAN], &vid);
2500 if (err)
2501 return err;
2502
2468 err = -EOPNOTSUPP; 2503 err = -EOPNOTSUPP;
2469 2504
2470 /* Support fdb on master device the net/bridge default case */ 2505 /* Support fdb on master device the net/bridge default case */
@@ -2474,7 +2509,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2474 const struct net_device_ops *ops = br_dev->netdev_ops; 2509 const struct net_device_ops *ops = br_dev->netdev_ops;
2475 2510
2476 if (ops->ndo_fdb_del) 2511 if (ops->ndo_fdb_del)
2477 err = ops->ndo_fdb_del(ndm, tb, dev, addr); 2512 err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid);
2478 2513
2479 if (err) 2514 if (err)
2480 goto out; 2515 goto out;
@@ -2485,9 +2520,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2485 /* Embedded bridge, macvlan, and any other device support */ 2520 /* Embedded bridge, macvlan, and any other device support */
2486 if (ndm->ndm_flags & NTF_SELF) { 2521 if (ndm->ndm_flags & NTF_SELF) {
2487 if (dev->netdev_ops->ndo_fdb_del) 2522 if (dev->netdev_ops->ndo_fdb_del)
2488 err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr); 2523 err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr,
2524 vid);
2489 else 2525 else
2490 err = ndo_dflt_fdb_del(ndm, tb, dev, addr); 2526 err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid);
2491 2527
2492 if (!err) { 2528 if (!err) {
2493 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH); 2529 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);