aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Shearman <rshearma@brocade.com>2015-04-22 06:14:37 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-22 14:24:54 -0400
commit03c57747a7020a28a200e7e920fb48ecdc9b0fb8 (patch)
tree012bd8131aa759a62667ea02fe87fa3328b16d65
parent909d9faae2a447110aa061070145297fffe129cb (diff)
mpls: Per-device MPLS state
Add per-device MPLS state to supported interfaces. Use the presence of this state in mpls_route_add to determine that this is a supported interface. Use the presence of mpls_dev to drop packets that arrived on an unsupported interface - previously they were allowed through. Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Robert Shearman <rshearma@brocade.com> Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--net/mpls/af_mpls.c50
-rw-r--r--net/mpls/internal.h3
3 files changed, 55 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bcbde799ec69..dae106a3a998 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -60,6 +60,7 @@ struct phy_device;
60struct wireless_dev; 60struct wireless_dev;
61/* 802.15.4 specific */ 61/* 802.15.4 specific */
62struct wpan_dev; 62struct wpan_dev;
63struct mpls_dev;
63 64
64void netdev_set_default_ethtool_ops(struct net_device *dev, 65void netdev_set_default_ethtool_ops(struct net_device *dev,
65 const struct ethtool_ops *ops); 66 const struct ethtool_ops *ops);
@@ -1627,6 +1628,9 @@ struct net_device {
1627 void *ax25_ptr; 1628 void *ax25_ptr;
1628 struct wireless_dev *ieee80211_ptr; 1629 struct wireless_dev *ieee80211_ptr;
1629 struct wpan_dev *ieee802154_ptr; 1630 struct wpan_dev *ieee802154_ptr;
1631#if IS_ENABLED(CONFIG_MPLS_ROUTING)
1632 struct mpls_dev __rcu *mpls_ptr;
1633#endif
1630 1634
1631/* 1635/*
1632 * Cache lines mostly used on receive path (including eth_type_trans()) 1636 * Cache lines mostly used on receive path (including eth_type_trans())
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index db8a2ea6d4de..ad45017eed99 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -53,6 +53,11 @@ static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
53 return rt; 53 return rt;
54} 54}
55 55
56static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
57{
58 return rcu_dereference_rtnl(dev->mpls_ptr);
59}
60
56static bool mpls_output_possible(const struct net_device *dev) 61static bool mpls_output_possible(const struct net_device *dev)
57{ 62{
58 return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev); 63 return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev);
@@ -136,6 +141,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
136 struct mpls_route *rt; 141 struct mpls_route *rt;
137 struct mpls_entry_decoded dec; 142 struct mpls_entry_decoded dec;
138 struct net_device *out_dev; 143 struct net_device *out_dev;
144 struct mpls_dev *mdev;
139 unsigned int hh_len; 145 unsigned int hh_len;
140 unsigned int new_header_size; 146 unsigned int new_header_size;
141 unsigned int mtu; 147 unsigned int mtu;
@@ -143,6 +149,10 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
143 149
144 /* Careful this entire function runs inside of an rcu critical section */ 150 /* Careful this entire function runs inside of an rcu critical section */
145 151
152 mdev = mpls_dev_get(dev);
153 if (!mdev)
154 goto drop;
155
146 if (skb->pkt_type != PACKET_HOST) 156 if (skb->pkt_type != PACKET_HOST)
147 goto drop; 157 goto drop;
148 158
@@ -352,9 +362,9 @@ static int mpls_route_add(struct mpls_route_config *cfg)
352 if (!dev) 362 if (!dev)
353 goto errout; 363 goto errout;
354 364
355 /* For now just support ethernet devices */ 365 /* Ensure this is a supported device */
356 err = -EINVAL; 366 err = -EINVAL;
357 if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) 367 if (!mpls_dev_get(dev))
358 goto errout; 368 goto errout;
359 369
360 err = -EINVAL; 370 err = -EINVAL;
@@ -428,10 +438,27 @@ errout:
428 return err; 438 return err;
429} 439}
430 440
441static struct mpls_dev *mpls_add_dev(struct net_device *dev)
442{
443 struct mpls_dev *mdev;
444 int err = -ENOMEM;
445
446 ASSERT_RTNL();
447
448 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
449 if (!mdev)
450 return ERR_PTR(err);
451
452 rcu_assign_pointer(dev->mpls_ptr, mdev);
453
454 return mdev;
455}
456
431static void mpls_ifdown(struct net_device *dev) 457static void mpls_ifdown(struct net_device *dev)
432{ 458{
433 struct mpls_route __rcu **platform_label; 459 struct mpls_route __rcu **platform_label;
434 struct net *net = dev_net(dev); 460 struct net *net = dev_net(dev);
461 struct mpls_dev *mdev;
435 unsigned index; 462 unsigned index;
436 463
437 platform_label = rtnl_dereference(net->mpls.platform_label); 464 platform_label = rtnl_dereference(net->mpls.platform_label);
@@ -443,14 +470,33 @@ static void mpls_ifdown(struct net_device *dev)
443 continue; 470 continue;
444 rt->rt_dev = NULL; 471 rt->rt_dev = NULL;
445 } 472 }
473
474 mdev = mpls_dev_get(dev);
475 if (!mdev)
476 return;
477
478 RCU_INIT_POINTER(dev->mpls_ptr, NULL);
479
480 kfree(mdev);
446} 481}
447 482
448static int mpls_dev_notify(struct notifier_block *this, unsigned long event, 483static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
449 void *ptr) 484 void *ptr)
450{ 485{
451 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 486 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
487 struct mpls_dev *mdev;
452 488
453 switch(event) { 489 switch(event) {
490 case NETDEV_REGISTER:
491 /* For now just support ethernet devices */
492 if ((dev->type == ARPHRD_ETHER) ||
493 (dev->type == ARPHRD_LOOPBACK)) {
494 mdev = mpls_add_dev(dev);
495 if (IS_ERR(mdev))
496 return notifier_from_errno(PTR_ERR(mdev));
497 }
498 break;
499
454 case NETDEV_UNREGISTER: 500 case NETDEV_UNREGISTER:
455 mpls_ifdown(dev); 501 mpls_ifdown(dev);
456 break; 502 break;
diff --git a/net/mpls/internal.h b/net/mpls/internal.h
index fb6de92052c4..8090cb3099b4 100644
--- a/net/mpls/internal.h
+++ b/net/mpls/internal.h
@@ -22,6 +22,9 @@ struct mpls_entry_decoded {
22 u8 bos; 22 u8 bos;
23}; 23};
24 24
25struct mpls_dev {
26};
27
25struct sk_buff; 28struct sk_buff;
26 29
27static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb) 30static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)