aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan/ipvlan_main.c
diff options
context:
space:
mode:
authorMahesh Bandewar <maheshb@google.com>2017-10-26 18:09:21 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-29 05:39:57 -0400
commita190d04db93710ae166749055b6985397c6d13f5 (patch)
tree32db41a469cc840fda9c52aad23369fe02ab2cb7 /drivers/net/ipvlan/ipvlan_main.c
parent995231c820e3bd3633cb38bf4ea6f2541e1da331 (diff)
ipvlan: introduce 'private' attribute for all existing modes.
IPvlan has always operated in bridge mode. However there are scenarios where each slave should be able to talk through the master device but not necessarily across each other. Think of an environment where each of a namespace is a private and independant customer. In this scenario the machine which is hosting these namespaces neither want to tell who their neighbor is nor the individual namespaces care to talk to neighbor on short-circuited network path. This patch implements the mode that is very similar to the 'private' mode in macvlan where individual slaves can send and receive traffic through the master device, just that they can not talk among slave devices. Signed-off-by: Mahesh Bandewar <maheshb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_main.c')
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index f0ab55df57f1..4368afb1934c 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -462,11 +462,24 @@ static int ipvlan_nl_changelink(struct net_device *dev,
462 struct ipvl_port *port = ipvlan_port_get_rtnl(ipvlan->phy_dev); 462 struct ipvl_port *port = ipvlan_port_get_rtnl(ipvlan->phy_dev);
463 int err = 0; 463 int err = 0;
464 464
465 if (data && data[IFLA_IPVLAN_MODE]) { 465 if (!data)
466 return 0;
467
468 if (data[IFLA_IPVLAN_MODE]) {
466 u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]); 469 u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
467 470
468 err = ipvlan_set_port_mode(port, nmode); 471 err = ipvlan_set_port_mode(port, nmode);
469 } 472 }
473
474 if (!err && data[IFLA_IPVLAN_FLAGS]) {
475 u16 flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]);
476
477 if (flags & IPVLAN_F_PRIVATE)
478 ipvlan_mark_private(port);
479 else
480 ipvlan_clear_private(port);
481 }
482
470 return err; 483 return err;
471} 484}
472 485
@@ -474,18 +487,30 @@ static size_t ipvlan_nl_getsize(const struct net_device *dev)
474{ 487{
475 return (0 488 return (0
476 + nla_total_size(2) /* IFLA_IPVLAN_MODE */ 489 + nla_total_size(2) /* IFLA_IPVLAN_MODE */
490 + nla_total_size(2) /* IFLA_IPVLAN_FLAGS */
477 ); 491 );
478} 492}
479 493
480static int ipvlan_nl_validate(struct nlattr *tb[], struct nlattr *data[], 494static int ipvlan_nl_validate(struct nlattr *tb[], struct nlattr *data[],
481 struct netlink_ext_ack *extack) 495 struct netlink_ext_ack *extack)
482{ 496{
483 if (data && data[IFLA_IPVLAN_MODE]) { 497 if (!data)
498 return 0;
499
500 if (data[IFLA_IPVLAN_MODE]) {
484 u16 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]); 501 u16 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
485 502
486 if (mode < IPVLAN_MODE_L2 || mode >= IPVLAN_MODE_MAX) 503 if (mode < IPVLAN_MODE_L2 || mode >= IPVLAN_MODE_MAX)
487 return -EINVAL; 504 return -EINVAL;
488 } 505 }
506 if (data[IFLA_IPVLAN_FLAGS]) {
507 u16 flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]);
508
509 /* Only one bit is used at this moment. */
510 if (flags & ~IPVLAN_F_PRIVATE)
511 return -EINVAL;
512 }
513
489 return 0; 514 return 0;
490} 515}
491 516
@@ -502,6 +527,8 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb,
502 ret = -EMSGSIZE; 527 ret = -EMSGSIZE;
503 if (nla_put_u16(skb, IFLA_IPVLAN_MODE, port->mode)) 528 if (nla_put_u16(skb, IFLA_IPVLAN_MODE, port->mode))
504 goto err; 529 goto err;
530 if (nla_put_u16(skb, IFLA_IPVLAN_FLAGS, port->flags))
531 goto err;
505 532
506 return 0; 533 return 0;
507 534
@@ -549,6 +576,12 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
549 ipvlan_adjust_mtu(ipvlan, phy_dev); 576 ipvlan_adjust_mtu(ipvlan, phy_dev);
550 INIT_LIST_HEAD(&ipvlan->addrs); 577 INIT_LIST_HEAD(&ipvlan->addrs);
551 578
579 /* Flags are per port and latest update overrides. User has
580 * to be consistent in setting it just like the mode attribute.
581 */
582 if (data && data[IFLA_IPVLAN_FLAGS])
583 ipvlan->port->flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]);
584
552 /* If the port-id base is at the MAX value, then wrap it around and 585 /* If the port-id base is at the MAX value, then wrap it around and
553 * begin from 0x1 again. This may be due to a busy system where lots 586 * begin from 0x1 again. This may be due to a busy system where lots
554 * of slaves are getting created and deleted. 587 * of slaves are getting created and deleted.
@@ -644,6 +677,7 @@ EXPORT_SYMBOL_GPL(ipvlan_link_setup);
644static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] = 677static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] =
645{ 678{
646 [IFLA_IPVLAN_MODE] = { .type = NLA_U16 }, 679 [IFLA_IPVLAN_MODE] = { .type = NLA_U16 },
680 [IFLA_IPVLAN_FLAGS] = { .type = NLA_U16 },
647}; 681};
648 682
649static struct rtnl_link_ops ipvlan_link_ops = { 683static struct rtnl_link_ops ipvlan_link_ops = {