diff options
-rw-r--r-- | Documentation/networking/mpls-sysctl.txt | 9 | ||||
-rw-r--r-- | net/mpls/af_mpls.c | 68 | ||||
-rw-r--r-- | net/mpls/internal.h | 3 |
3 files changed, 78 insertions, 2 deletions
diff --git a/Documentation/networking/mpls-sysctl.txt b/Documentation/networking/mpls-sysctl.txt index 639ddf0ece9b..9ed15f86c17c 100644 --- a/Documentation/networking/mpls-sysctl.txt +++ b/Documentation/networking/mpls-sysctl.txt | |||
@@ -18,3 +18,12 @@ platform_labels - INTEGER | |||
18 | 18 | ||
19 | Possible values: 0 - 1048575 | 19 | Possible values: 0 - 1048575 |
20 | Default: 0 | 20 | Default: 0 |
21 | |||
22 | conf/<interface>/input - BOOL | ||
23 | Control whether packets can be input on this interface. | ||
24 | |||
25 | If disabled, packets will be discarded without further | ||
26 | processing. | ||
27 | |||
28 | 0 - disabled (default) | ||
29 | not 0 - enabled | ||
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index ad45017eed99..9fdd94cba83e 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -150,7 +150,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
150 | /* Careful this entire function runs inside of an rcu critical section */ | 150 | /* Careful this entire function runs inside of an rcu critical section */ |
151 | 151 | ||
152 | mdev = mpls_dev_get(dev); | 152 | mdev = mpls_dev_get(dev); |
153 | if (!mdev) | 153 | if (!mdev || !mdev->input_enabled) |
154 | goto drop; | 154 | goto drop; |
155 | 155 | ||
156 | if (skb->pkt_type != PACKET_HOST) | 156 | if (skb->pkt_type != PACKET_HOST) |
@@ -438,6 +438,60 @@ errout: | |||
438 | return err; | 438 | return err; |
439 | } | 439 | } |
440 | 440 | ||
441 | #define MPLS_PERDEV_SYSCTL_OFFSET(field) \ | ||
442 | (&((struct mpls_dev *)0)->field) | ||
443 | |||
444 | static const struct ctl_table mpls_dev_table[] = { | ||
445 | { | ||
446 | .procname = "input", | ||
447 | .maxlen = sizeof(int), | ||
448 | .mode = 0644, | ||
449 | .proc_handler = proc_dointvec, | ||
450 | .data = MPLS_PERDEV_SYSCTL_OFFSET(input_enabled), | ||
451 | }, | ||
452 | { } | ||
453 | }; | ||
454 | |||
455 | static int mpls_dev_sysctl_register(struct net_device *dev, | ||
456 | struct mpls_dev *mdev) | ||
457 | { | ||
458 | char path[sizeof("net/mpls/conf/") + IFNAMSIZ]; | ||
459 | struct ctl_table *table; | ||
460 | int i; | ||
461 | |||
462 | table = kmemdup(&mpls_dev_table, sizeof(mpls_dev_table), GFP_KERNEL); | ||
463 | if (!table) | ||
464 | goto out; | ||
465 | |||
466 | /* Table data contains only offsets relative to the base of | ||
467 | * the mdev at this point, so make them absolute. | ||
468 | */ | ||
469 | for (i = 0; i < ARRAY_SIZE(mpls_dev_table); i++) | ||
470 | table[i].data = (char *)mdev + (uintptr_t)table[i].data; | ||
471 | |||
472 | snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name); | ||
473 | |||
474 | mdev->sysctl = register_net_sysctl(dev_net(dev), path, table); | ||
475 | if (!mdev->sysctl) | ||
476 | goto free; | ||
477 | |||
478 | return 0; | ||
479 | |||
480 | free: | ||
481 | kfree(table); | ||
482 | out: | ||
483 | return -ENOBUFS; | ||
484 | } | ||
485 | |||
486 | static void mpls_dev_sysctl_unregister(struct mpls_dev *mdev) | ||
487 | { | ||
488 | struct ctl_table *table; | ||
489 | |||
490 | table = mdev->sysctl->ctl_table_arg; | ||
491 | unregister_net_sysctl_table(mdev->sysctl); | ||
492 | kfree(table); | ||
493 | } | ||
494 | |||
441 | static struct mpls_dev *mpls_add_dev(struct net_device *dev) | 495 | static struct mpls_dev *mpls_add_dev(struct net_device *dev) |
442 | { | 496 | { |
443 | struct mpls_dev *mdev; | 497 | struct mpls_dev *mdev; |
@@ -449,9 +503,17 @@ static struct mpls_dev *mpls_add_dev(struct net_device *dev) | |||
449 | if (!mdev) | 503 | if (!mdev) |
450 | return ERR_PTR(err); | 504 | return ERR_PTR(err); |
451 | 505 | ||
506 | err = mpls_dev_sysctl_register(dev, mdev); | ||
507 | if (err) | ||
508 | goto free; | ||
509 | |||
452 | rcu_assign_pointer(dev->mpls_ptr, mdev); | 510 | rcu_assign_pointer(dev->mpls_ptr, mdev); |
453 | 511 | ||
454 | return mdev; | 512 | return mdev; |
513 | |||
514 | free: | ||
515 | kfree(mdev); | ||
516 | return ERR_PTR(err); | ||
455 | } | 517 | } |
456 | 518 | ||
457 | static void mpls_ifdown(struct net_device *dev) | 519 | static void mpls_ifdown(struct net_device *dev) |
@@ -475,6 +537,8 @@ static void mpls_ifdown(struct net_device *dev) | |||
475 | if (!mdev) | 537 | if (!mdev) |
476 | return; | 538 | return; |
477 | 539 | ||
540 | mpls_dev_sysctl_unregister(mdev); | ||
541 | |||
478 | RCU_INIT_POINTER(dev->mpls_ptr, NULL); | 542 | RCU_INIT_POINTER(dev->mpls_ptr, NULL); |
479 | 543 | ||
480 | kfree(mdev); | 544 | kfree(mdev); |
@@ -958,7 +1022,7 @@ static int mpls_platform_labels(struct ctl_table *table, int write, | |||
958 | return ret; | 1022 | return ret; |
959 | } | 1023 | } |
960 | 1024 | ||
961 | static struct ctl_table mpls_table[] = { | 1025 | static const struct ctl_table mpls_table[] = { |
962 | { | 1026 | { |
963 | .procname = "platform_labels", | 1027 | .procname = "platform_labels", |
964 | .data = NULL, | 1028 | .data = NULL, |
diff --git a/net/mpls/internal.h b/net/mpls/internal.h index 8090cb3099b4..693877d69606 100644 --- a/net/mpls/internal.h +++ b/net/mpls/internal.h | |||
@@ -23,6 +23,9 @@ struct mpls_entry_decoded { | |||
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct mpls_dev { | 25 | struct mpls_dev { |
26 | int input_enabled; | ||
27 | |||
28 | struct ctl_table_header *sysctl; | ||
26 | }; | 29 | }; |
27 | 30 | ||
28 | struct sk_buff; | 31 | struct sk_buff; |