aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2014-11-28 08:34:15 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-02 23:01:18 -0500
commitf6f6424ba773da6221ecaaa70973eb4dacfa03b2 (patch)
tree76b4c5cea45c1a569d6cbd2f896e07f6b45d523e /net
parent93859b13fa7ecef9d4d8bab4a7acc9f212c8fce2 (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_fdb.c39
-rw-r--r--net/bridge/br_private.h4
-rw-r--r--net/core/rtnetlink.c50
3 files changed, 49 insertions, 44 deletions
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);