aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/mpls-sysctl.txt9
-rw-r--r--net/mpls/af_mpls.c68
-rw-r--r--net/mpls/internal.h3
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
22conf/<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
444static 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
455static 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
480free:
481 kfree(table);
482out:
483 return -ENOBUFS;
484}
485
486static 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
441static struct mpls_dev *mpls_add_dev(struct net_device *dev) 495static 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
514free:
515 kfree(mdev);
516 return ERR_PTR(err);
455} 517}
456 518
457static void mpls_ifdown(struct net_device *dev) 519static 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
961static struct ctl_table mpls_table[] = { 1025static 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
25struct mpls_dev { 25struct mpls_dev {
26 int input_enabled;
27
28 struct ctl_table_header *sysctl;
26}; 29};
27 30
28struct sk_buff; 31struct sk_buff;