Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Robert Shearman and committed by
David S. Miller
03c57747 909d9faa

+55 -2
+4
include/linux/netdevice.h
··· 60 60 struct wireless_dev; 61 61 /* 802.15.4 specific */ 62 62 struct wpan_dev; 63 + struct mpls_dev; 63 64 64 65 void netdev_set_default_ethtool_ops(struct net_device *dev, 65 66 const struct ethtool_ops *ops); ··· 1628 1627 void *ax25_ptr; 1629 1628 struct wireless_dev *ieee80211_ptr; 1630 1629 struct wpan_dev *ieee802154_ptr; 1630 + #if IS_ENABLED(CONFIG_MPLS_ROUTING) 1631 + struct mpls_dev __rcu *mpls_ptr; 1632 + #endif 1631 1633 1632 1634 /* 1633 1635 * Cache lines mostly used on receive path (including eth_type_trans())
+48 -2
net/mpls/af_mpls.c
··· 53 53 return rt; 54 54 } 55 55 56 + static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev) 57 + { 58 + return rcu_dereference_rtnl(dev->mpls_ptr); 59 + } 60 + 56 61 static bool mpls_output_possible(const struct net_device *dev) 57 62 { 58 63 return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev); ··· 141 136 struct mpls_route *rt; 142 137 struct mpls_entry_decoded dec; 143 138 struct net_device *out_dev; 139 + struct mpls_dev *mdev; 144 140 unsigned int hh_len; 145 141 unsigned int new_header_size; 146 142 unsigned int mtu; 147 143 int err; 148 144 149 145 /* Careful this entire function runs inside of an rcu critical section */ 146 + 147 + mdev = mpls_dev_get(dev); 148 + if (!mdev) 149 + goto drop; 150 150 151 151 if (skb->pkt_type != PACKET_HOST) 152 152 goto drop; ··· 362 352 if (!dev) 363 353 goto errout; 364 354 365 - /* For now just support ethernet devices */ 355 + /* Ensure this is a supported device */ 366 356 err = -EINVAL; 367 - if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) 357 + if (!mpls_dev_get(dev)) 368 358 goto errout; 369 359 370 360 err = -EINVAL; ··· 438 428 return err; 439 429 } 440 430 431 + static struct mpls_dev *mpls_add_dev(struct net_device *dev) 432 + { 433 + struct mpls_dev *mdev; 434 + int err = -ENOMEM; 435 + 436 + ASSERT_RTNL(); 437 + 438 + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); 439 + if (!mdev) 440 + return ERR_PTR(err); 441 + 442 + rcu_assign_pointer(dev->mpls_ptr, mdev); 443 + 444 + return mdev; 445 + } 446 + 441 447 static void mpls_ifdown(struct net_device *dev) 442 448 { 443 449 struct mpls_route __rcu **platform_label; 444 450 struct net *net = dev_net(dev); 451 + struct mpls_dev *mdev; 445 452 unsigned index; 446 453 447 454 platform_label = rtnl_dereference(net->mpls.platform_label); ··· 470 443 continue; 471 444 rt->rt_dev = NULL; 472 445 } 446 + 447 + mdev = mpls_dev_get(dev); 448 + if (!mdev) 449 + return; 450 + 451 + RCU_INIT_POINTER(dev->mpls_ptr, NULL); 452 + 453 + kfree(mdev); 473 454 } 474 455 475 456 static int mpls_dev_notify(struct notifier_block *this, unsigned long event, 476 457 void *ptr) 477 458 { 478 459 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 460 + struct mpls_dev *mdev; 479 461 480 462 switch(event) { 463 + case NETDEV_REGISTER: 464 + /* For now just support ethernet devices */ 465 + if ((dev->type == ARPHRD_ETHER) || 466 + (dev->type == ARPHRD_LOOPBACK)) { 467 + mdev = mpls_add_dev(dev); 468 + if (IS_ERR(mdev)) 469 + return notifier_from_errno(PTR_ERR(mdev)); 470 + } 471 + break; 472 + 481 473 case NETDEV_UNREGISTER: 482 474 mpls_ifdown(dev); 483 475 break;
+3
net/mpls/internal.h
··· 22 22 u8 bos; 23 23 }; 24 24 25 + struct mpls_dev { 26 + }; 27 + 25 28 struct sk_buff; 26 29 27 30 static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)