diff options
author | Vlad Yasevich <vyasevic@redhat.com> | 2013-02-13 07:00:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-13 19:41:46 -0500 |
commit | 407af3299ef1ac7e87ce3fb530e32a009d1a9efd (patch) | |
tree | 9572e0b02eb9f6c2952b490f3a79f4b790fcea3c /net/core | |
parent | 85f46c6baef1486ce20e13dd7cdea5dd15be2a90 (diff) |
bridge: Add netlink interface to configure vlans on bridge ports
Add a netlink interface to add and remove vlan configuration on bridge port.
The interface uses the RTM_SETLINK message and encodes the vlan
configuration inside the IFLA_AF_SPEC. It is possble to include multiple
vlans to either add or remove in a single message.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/rtnetlink.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c1e4db60eeca..2c9ccbfbd93c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -2464,6 +2464,77 @@ out: | |||
2464 | return err; | 2464 | return err; |
2465 | } | 2465 | } |
2466 | 2466 | ||
2467 | static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
2468 | void *arg) | ||
2469 | { | ||
2470 | struct net *net = sock_net(skb->sk); | ||
2471 | struct ifinfomsg *ifm; | ||
2472 | struct net_device *dev; | ||
2473 | struct nlattr *br_spec, *attr = NULL; | ||
2474 | int rem, err = -EOPNOTSUPP; | ||
2475 | u16 oflags, flags = 0; | ||
2476 | bool have_flags = false; | ||
2477 | |||
2478 | if (nlmsg_len(nlh) < sizeof(*ifm)) | ||
2479 | return -EINVAL; | ||
2480 | |||
2481 | ifm = nlmsg_data(nlh); | ||
2482 | if (ifm->ifi_family != AF_BRIDGE) | ||
2483 | return -EPFNOSUPPORT; | ||
2484 | |||
2485 | dev = __dev_get_by_index(net, ifm->ifi_index); | ||
2486 | if (!dev) { | ||
2487 | pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n"); | ||
2488 | return -ENODEV; | ||
2489 | } | ||
2490 | |||
2491 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); | ||
2492 | if (br_spec) { | ||
2493 | nla_for_each_nested(attr, br_spec, rem) { | ||
2494 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | ||
2495 | have_flags = true; | ||
2496 | flags = nla_get_u16(attr); | ||
2497 | break; | ||
2498 | } | ||
2499 | } | ||
2500 | } | ||
2501 | |||
2502 | oflags = flags; | ||
2503 | |||
2504 | if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { | ||
2505 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | ||
2506 | |||
2507 | if (!br_dev || !br_dev->netdev_ops->ndo_bridge_dellink) { | ||
2508 | err = -EOPNOTSUPP; | ||
2509 | goto out; | ||
2510 | } | ||
2511 | |||
2512 | err = br_dev->netdev_ops->ndo_bridge_dellink(dev, nlh); | ||
2513 | if (err) | ||
2514 | goto out; | ||
2515 | |||
2516 | flags &= ~BRIDGE_FLAGS_MASTER; | ||
2517 | } | ||
2518 | |||
2519 | if ((flags & BRIDGE_FLAGS_SELF)) { | ||
2520 | if (!dev->netdev_ops->ndo_bridge_dellink) | ||
2521 | err = -EOPNOTSUPP; | ||
2522 | else | ||
2523 | err = dev->netdev_ops->ndo_bridge_dellink(dev, nlh); | ||
2524 | |||
2525 | if (!err) | ||
2526 | flags &= ~BRIDGE_FLAGS_SELF; | ||
2527 | } | ||
2528 | |||
2529 | if (have_flags) | ||
2530 | memcpy(nla_data(attr), &flags, sizeof(flags)); | ||
2531 | /* Generate event to notify upper layer of bridge change */ | ||
2532 | if (!err) | ||
2533 | err = rtnl_bridge_notify(dev, oflags); | ||
2534 | out: | ||
2535 | return err; | ||
2536 | } | ||
2537 | |||
2467 | /* Protected by RTNL sempahore. */ | 2538 | /* Protected by RTNL sempahore. */ |
2468 | static struct rtattr **rta_buf; | 2539 | static struct rtattr **rta_buf; |
2469 | static int rtattr_max; | 2540 | static int rtattr_max; |
@@ -2647,6 +2718,7 @@ void __init rtnetlink_init(void) | |||
2647 | rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL); | 2718 | rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL); |
2648 | 2719 | ||
2649 | rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL); | 2720 | rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL); |
2721 | rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, NULL); | ||
2650 | rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL); | 2722 | rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL); |
2651 | } | 2723 | } |
2652 | 2724 | ||