diff options
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 173 |
1 files changed, 98 insertions, 75 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b22ca2d1cebc..7490f3f2db8b 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -187,7 +187,7 @@ int unregister_qdisc(struct Qdisc_ops *qops) | |||
187 | int err = -ENOENT; | 187 | int err = -ENOENT; |
188 | 188 | ||
189 | write_lock(&qdisc_mod_lock); | 189 | write_lock(&qdisc_mod_lock); |
190 | for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next) | 190 | for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next) |
191 | if (q == qops) | 191 | if (q == qops) |
192 | break; | 192 | break; |
193 | if (q) { | 193 | if (q) { |
@@ -321,7 +321,9 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab) | |||
321 | if (!tab || --tab->refcnt) | 321 | if (!tab || --tab->refcnt) |
322 | return; | 322 | return; |
323 | 323 | ||
324 | for (rtabp = &qdisc_rtab_list; (rtab=*rtabp) != NULL; rtabp = &rtab->next) { | 324 | for (rtabp = &qdisc_rtab_list; |
325 | (rtab = *rtabp) != NULL; | ||
326 | rtabp = &rtab->next) { | ||
325 | if (rtab == tab) { | 327 | if (rtab == tab) { |
326 | *rtabp = rtab->next; | 328 | *rtabp = rtab->next; |
327 | kfree(rtab); | 329 | kfree(rtab); |
@@ -396,6 +398,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) | |||
396 | return stab; | 398 | return stab; |
397 | } | 399 | } |
398 | 400 | ||
401 | static void stab_kfree_rcu(struct rcu_head *head) | ||
402 | { | ||
403 | kfree(container_of(head, struct qdisc_size_table, rcu)); | ||
404 | } | ||
405 | |||
399 | void qdisc_put_stab(struct qdisc_size_table *tab) | 406 | void qdisc_put_stab(struct qdisc_size_table *tab) |
400 | { | 407 | { |
401 | if (!tab) | 408 | if (!tab) |
@@ -405,7 +412,7 @@ void qdisc_put_stab(struct qdisc_size_table *tab) | |||
405 | 412 | ||
406 | if (--tab->refcnt == 0) { | 413 | if (--tab->refcnt == 0) { |
407 | list_del(&tab->list); | 414 | list_del(&tab->list); |
408 | kfree(tab); | 415 | call_rcu_bh(&tab->rcu, stab_kfree_rcu); |
409 | } | 416 | } |
410 | 417 | ||
411 | spin_unlock(&qdisc_stab_lock); | 418 | spin_unlock(&qdisc_stab_lock); |
@@ -428,7 +435,7 @@ nla_put_failure: | |||
428 | return -1; | 435 | return -1; |
429 | } | 436 | } |
430 | 437 | ||
431 | void qdisc_calculate_pkt_len(struct sk_buff *skb, struct qdisc_size_table *stab) | 438 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_table *stab) |
432 | { | 439 | { |
433 | int pkt_len, slot; | 440 | int pkt_len, slot; |
434 | 441 | ||
@@ -454,14 +461,13 @@ out: | |||
454 | pkt_len = 1; | 461 | pkt_len = 1; |
455 | qdisc_skb_cb(skb)->pkt_len = pkt_len; | 462 | qdisc_skb_cb(skb)->pkt_len = pkt_len; |
456 | } | 463 | } |
457 | EXPORT_SYMBOL(qdisc_calculate_pkt_len); | 464 | EXPORT_SYMBOL(__qdisc_calculate_pkt_len); |
458 | 465 | ||
459 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) | 466 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) |
460 | { | 467 | { |
461 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { | 468 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { |
462 | printk(KERN_WARNING | 469 | pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", |
463 | "%s: %s qdisc %X: is non-work-conserving?\n", | 470 | txt, qdisc->ops->id, qdisc->handle >> 16); |
464 | txt, qdisc->ops->id, qdisc->handle >> 16); | ||
465 | qdisc->flags |= TCQ_F_WARN_NONWC; | 471 | qdisc->flags |= TCQ_F_WARN_NONWC; |
466 | } | 472 | } |
467 | } | 473 | } |
@@ -472,7 +478,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
472 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | 478 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, |
473 | timer); | 479 | timer); |
474 | 480 | ||
475 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 481 | qdisc_unthrottled(wd->qdisc); |
476 | __netif_schedule(qdisc_root(wd->qdisc)); | 482 | __netif_schedule(qdisc_root(wd->qdisc)); |
477 | 483 | ||
478 | return HRTIMER_NORESTART; | 484 | return HRTIMER_NORESTART; |
@@ -494,7 +500,7 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) | |||
494 | &qdisc_root_sleeping(wd->qdisc)->state)) | 500 | &qdisc_root_sleeping(wd->qdisc)->state)) |
495 | return; | 501 | return; |
496 | 502 | ||
497 | wd->qdisc->flags |= TCQ_F_THROTTLED; | 503 | qdisc_throttled(wd->qdisc); |
498 | time = ktime_set(0, 0); | 504 | time = ktime_set(0, 0); |
499 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); | 505 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); |
500 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); | 506 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); |
@@ -504,7 +510,7 @@ EXPORT_SYMBOL(qdisc_watchdog_schedule); | |||
504 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) | 510 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) |
505 | { | 511 | { |
506 | hrtimer_cancel(&wd->timer); | 512 | hrtimer_cancel(&wd->timer); |
507 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 513 | qdisc_unthrottled(wd->qdisc); |
508 | } | 514 | } |
509 | EXPORT_SYMBOL(qdisc_watchdog_cancel); | 515 | EXPORT_SYMBOL(qdisc_watchdog_cancel); |
510 | 516 | ||
@@ -625,7 +631,7 @@ static u32 qdisc_alloc_handle(struct net_device *dev) | |||
625 | autohandle = TC_H_MAKE(0x80000000U, 0); | 631 | autohandle = TC_H_MAKE(0x80000000U, 0); |
626 | } while (qdisc_lookup(dev, autohandle) && --i > 0); | 632 | } while (qdisc_lookup(dev, autohandle) && --i > 0); |
627 | 633 | ||
628 | return i>0 ? autohandle : 0; | 634 | return i > 0 ? autohandle : 0; |
629 | } | 635 | } |
630 | 636 | ||
631 | void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | 637 | void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) |
@@ -834,7 +840,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
834 | err = PTR_ERR(stab); | 840 | err = PTR_ERR(stab); |
835 | goto err_out4; | 841 | goto err_out4; |
836 | } | 842 | } |
837 | sch->stab = stab; | 843 | rcu_assign_pointer(sch->stab, stab); |
838 | } | 844 | } |
839 | if (tca[TCA_RATE]) { | 845 | if (tca[TCA_RATE]) { |
840 | spinlock_t *root_lock; | 846 | spinlock_t *root_lock; |
@@ -874,7 +880,7 @@ err_out4: | |||
874 | * Any broken qdiscs that would require a ops->reset() here? | 880 | * Any broken qdiscs that would require a ops->reset() here? |
875 | * The qdisc was never in action so it shouldn't be necessary. | 881 | * The qdisc was never in action so it shouldn't be necessary. |
876 | */ | 882 | */ |
877 | qdisc_put_stab(sch->stab); | 883 | qdisc_put_stab(rtnl_dereference(sch->stab)); |
878 | if (ops->destroy) | 884 | if (ops->destroy) |
879 | ops->destroy(sch); | 885 | ops->destroy(sch); |
880 | goto err_out3; | 886 | goto err_out3; |
@@ -882,7 +888,7 @@ err_out4: | |||
882 | 888 | ||
883 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | 889 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) |
884 | { | 890 | { |
885 | struct qdisc_size_table *stab = NULL; | 891 | struct qdisc_size_table *ostab, *stab = NULL; |
886 | int err = 0; | 892 | int err = 0; |
887 | 893 | ||
888 | if (tca[TCA_OPTIONS]) { | 894 | if (tca[TCA_OPTIONS]) { |
@@ -899,8 +905,9 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | |||
899 | return PTR_ERR(stab); | 905 | return PTR_ERR(stab); |
900 | } | 906 | } |
901 | 907 | ||
902 | qdisc_put_stab(sch->stab); | 908 | ostab = rtnl_dereference(sch->stab); |
903 | sch->stab = stab; | 909 | rcu_assign_pointer(sch->stab, stab); |
910 | qdisc_put_stab(ostab); | ||
904 | 911 | ||
905 | if (tca[TCA_RATE]) { | 912 | if (tca[TCA_RATE]) { |
906 | /* NB: ignores errors from replace_estimator | 913 | /* NB: ignores errors from replace_estimator |
@@ -915,9 +922,8 @@ out: | |||
915 | return 0; | 922 | return 0; |
916 | } | 923 | } |
917 | 924 | ||
918 | struct check_loop_arg | 925 | struct check_loop_arg { |
919 | { | 926 | struct qdisc_walker w; |
920 | struct qdisc_walker w; | ||
921 | struct Qdisc *p; | 927 | struct Qdisc *p; |
922 | int depth; | 928 | int depth; |
923 | }; | 929 | }; |
@@ -970,7 +976,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
970 | struct Qdisc *p = NULL; | 976 | struct Qdisc *p = NULL; |
971 | int err; | 977 | int err; |
972 | 978 | ||
973 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 979 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
980 | if (!dev) | ||
974 | return -ENODEV; | 981 | return -ENODEV; |
975 | 982 | ||
976 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 983 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -980,12 +987,12 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
980 | if (clid) { | 987 | if (clid) { |
981 | if (clid != TC_H_ROOT) { | 988 | if (clid != TC_H_ROOT) { |
982 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { | 989 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { |
983 | if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL) | 990 | p = qdisc_lookup(dev, TC_H_MAJ(clid)); |
991 | if (!p) | ||
984 | return -ENOENT; | 992 | return -ENOENT; |
985 | q = qdisc_leaf(p, clid); | 993 | q = qdisc_leaf(p, clid); |
986 | } else { /* ingress */ | 994 | } else if (dev_ingress_queue(dev)) { |
987 | if (dev_ingress_queue(dev)) | 995 | q = dev_ingress_queue(dev)->qdisc_sleeping; |
988 | q = dev_ingress_queue(dev)->qdisc_sleeping; | ||
989 | } | 996 | } |
990 | } else { | 997 | } else { |
991 | q = dev->qdisc; | 998 | q = dev->qdisc; |
@@ -996,7 +1003,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
996 | if (tcm->tcm_handle && q->handle != tcm->tcm_handle) | 1003 | if (tcm->tcm_handle && q->handle != tcm->tcm_handle) |
997 | return -EINVAL; | 1004 | return -EINVAL; |
998 | } else { | 1005 | } else { |
999 | if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL) | 1006 | q = qdisc_lookup(dev, tcm->tcm_handle); |
1007 | if (!q) | ||
1000 | return -ENOENT; | 1008 | return -ENOENT; |
1001 | } | 1009 | } |
1002 | 1010 | ||
@@ -1008,7 +1016,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1008 | return -EINVAL; | 1016 | return -EINVAL; |
1009 | if (q->handle == 0) | 1017 | if (q->handle == 0) |
1010 | return -ENOENT; | 1018 | return -ENOENT; |
1011 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) | 1019 | err = qdisc_graft(dev, p, skb, n, clid, NULL, q); |
1020 | if (err != 0) | ||
1012 | return err; | 1021 | return err; |
1013 | } else { | 1022 | } else { |
1014 | qdisc_notify(net, skb, n, clid, NULL, q); | 1023 | qdisc_notify(net, skb, n, clid, NULL, q); |
@@ -1017,7 +1026,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1017 | } | 1026 | } |
1018 | 1027 | ||
1019 | /* | 1028 | /* |
1020 | Create/change qdisc. | 1029 | * Create/change qdisc. |
1021 | */ | 1030 | */ |
1022 | 1031 | ||
1023 | static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | 1032 | static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) |
@@ -1036,7 +1045,8 @@ replay: | |||
1036 | clid = tcm->tcm_parent; | 1045 | clid = tcm->tcm_parent; |
1037 | q = p = NULL; | 1046 | q = p = NULL; |
1038 | 1047 | ||
1039 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1048 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
1049 | if (!dev) | ||
1040 | return -ENODEV; | 1050 | return -ENODEV; |
1041 | 1051 | ||
1042 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1052 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1046,12 +1056,12 @@ replay: | |||
1046 | if (clid) { | 1056 | if (clid) { |
1047 | if (clid != TC_H_ROOT) { | 1057 | if (clid != TC_H_ROOT) { |
1048 | if (clid != TC_H_INGRESS) { | 1058 | if (clid != TC_H_INGRESS) { |
1049 | if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL) | 1059 | p = qdisc_lookup(dev, TC_H_MAJ(clid)); |
1060 | if (!p) | ||
1050 | return -ENOENT; | 1061 | return -ENOENT; |
1051 | q = qdisc_leaf(p, clid); | 1062 | q = qdisc_leaf(p, clid); |
1052 | } else { /* ingress */ | 1063 | } else if (dev_ingress_queue_create(dev)) { |
1053 | if (dev_ingress_queue_create(dev)) | 1064 | q = dev_ingress_queue(dev)->qdisc_sleeping; |
1054 | q = dev_ingress_queue(dev)->qdisc_sleeping; | ||
1055 | } | 1065 | } |
1056 | } else { | 1066 | } else { |
1057 | q = dev->qdisc; | 1067 | q = dev->qdisc; |
@@ -1063,13 +1073,14 @@ replay: | |||
1063 | 1073 | ||
1064 | if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) { | 1074 | if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) { |
1065 | if (tcm->tcm_handle) { | 1075 | if (tcm->tcm_handle) { |
1066 | if (q && !(n->nlmsg_flags&NLM_F_REPLACE)) | 1076 | if (q && !(n->nlmsg_flags & NLM_F_REPLACE)) |
1067 | return -EEXIST; | 1077 | return -EEXIST; |
1068 | if (TC_H_MIN(tcm->tcm_handle)) | 1078 | if (TC_H_MIN(tcm->tcm_handle)) |
1069 | return -EINVAL; | 1079 | return -EINVAL; |
1070 | if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL) | 1080 | q = qdisc_lookup(dev, tcm->tcm_handle); |
1081 | if (!q) | ||
1071 | goto create_n_graft; | 1082 | goto create_n_graft; |
1072 | if (n->nlmsg_flags&NLM_F_EXCL) | 1083 | if (n->nlmsg_flags & NLM_F_EXCL) |
1073 | return -EEXIST; | 1084 | return -EEXIST; |
1074 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) | 1085 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) |
1075 | return -EINVAL; | 1086 | return -EINVAL; |
@@ -1079,7 +1090,7 @@ replay: | |||
1079 | atomic_inc(&q->refcnt); | 1090 | atomic_inc(&q->refcnt); |
1080 | goto graft; | 1091 | goto graft; |
1081 | } else { | 1092 | } else { |
1082 | if (q == NULL) | 1093 | if (!q) |
1083 | goto create_n_graft; | 1094 | goto create_n_graft; |
1084 | 1095 | ||
1085 | /* This magic test requires explanation. | 1096 | /* This magic test requires explanation. |
@@ -1101,9 +1112,9 @@ replay: | |||
1101 | * For now we select create/graft, if | 1112 | * For now we select create/graft, if |
1102 | * user gave KIND, which does not match existing. | 1113 | * user gave KIND, which does not match existing. |
1103 | */ | 1114 | */ |
1104 | if ((n->nlmsg_flags&NLM_F_CREATE) && | 1115 | if ((n->nlmsg_flags & NLM_F_CREATE) && |
1105 | (n->nlmsg_flags&NLM_F_REPLACE) && | 1116 | (n->nlmsg_flags & NLM_F_REPLACE) && |
1106 | ((n->nlmsg_flags&NLM_F_EXCL) || | 1117 | ((n->nlmsg_flags & NLM_F_EXCL) || |
1107 | (tca[TCA_KIND] && | 1118 | (tca[TCA_KIND] && |
1108 | nla_strcmp(tca[TCA_KIND], q->ops->id)))) | 1119 | nla_strcmp(tca[TCA_KIND], q->ops->id)))) |
1109 | goto create_n_graft; | 1120 | goto create_n_graft; |
@@ -1118,7 +1129,7 @@ replay: | |||
1118 | /* Change qdisc parameters */ | 1129 | /* Change qdisc parameters */ |
1119 | if (q == NULL) | 1130 | if (q == NULL) |
1120 | return -ENOENT; | 1131 | return -ENOENT; |
1121 | if (n->nlmsg_flags&NLM_F_EXCL) | 1132 | if (n->nlmsg_flags & NLM_F_EXCL) |
1122 | return -EEXIST; | 1133 | return -EEXIST; |
1123 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) | 1134 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) |
1124 | return -EINVAL; | 1135 | return -EINVAL; |
@@ -1128,7 +1139,7 @@ replay: | |||
1128 | return err; | 1139 | return err; |
1129 | 1140 | ||
1130 | create_n_graft: | 1141 | create_n_graft: |
1131 | if (!(n->nlmsg_flags&NLM_F_CREATE)) | 1142 | if (!(n->nlmsg_flags & NLM_F_CREATE)) |
1132 | return -ENOENT; | 1143 | return -ENOENT; |
1133 | if (clid == TC_H_INGRESS) { | 1144 | if (clid == TC_H_INGRESS) { |
1134 | if (dev_ingress_queue(dev)) | 1145 | if (dev_ingress_queue(dev)) |
@@ -1175,6 +1186,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
1175 | struct nlmsghdr *nlh; | 1186 | struct nlmsghdr *nlh; |
1176 | unsigned char *b = skb_tail_pointer(skb); | 1187 | unsigned char *b = skb_tail_pointer(skb); |
1177 | struct gnet_dump d; | 1188 | struct gnet_dump d; |
1189 | struct qdisc_size_table *stab; | ||
1178 | 1190 | ||
1179 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 1191 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
1180 | tcm = NLMSG_DATA(nlh); | 1192 | tcm = NLMSG_DATA(nlh); |
@@ -1190,7 +1202,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
1190 | goto nla_put_failure; | 1202 | goto nla_put_failure; |
1191 | q->qstats.qlen = q->q.qlen; | 1203 | q->qstats.qlen = q->q.qlen; |
1192 | 1204 | ||
1193 | if (q->stab && qdisc_dump_stab(skb, q->stab) < 0) | 1205 | stab = rtnl_dereference(q->stab); |
1206 | if (stab && qdisc_dump_stab(skb, stab) < 0) | ||
1194 | goto nla_put_failure; | 1207 | goto nla_put_failure; |
1195 | 1208 | ||
1196 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, | 1209 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, |
@@ -1234,16 +1247,19 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb, | |||
1234 | return -ENOBUFS; | 1247 | return -ENOBUFS; |
1235 | 1248 | ||
1236 | if (old && !tc_qdisc_dump_ignore(old)) { | 1249 | if (old && !tc_qdisc_dump_ignore(old)) { |
1237 | if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0) | 1250 | if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, |
1251 | 0, RTM_DELQDISC) < 0) | ||
1238 | goto err_out; | 1252 | goto err_out; |
1239 | } | 1253 | } |
1240 | if (new && !tc_qdisc_dump_ignore(new)) { | 1254 | if (new && !tc_qdisc_dump_ignore(new)) { |
1241 | if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0) | 1255 | if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, |
1256 | old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0) | ||
1242 | goto err_out; | 1257 | goto err_out; |
1243 | } | 1258 | } |
1244 | 1259 | ||
1245 | if (skb->len) | 1260 | if (skb->len) |
1246 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1261 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
1262 | n->nlmsg_flags & NLM_F_ECHO); | ||
1247 | 1263 | ||
1248 | err_out: | 1264 | err_out: |
1249 | kfree_skb(skb); | 1265 | kfree_skb(skb); |
@@ -1275,7 +1291,7 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, | |||
1275 | q_idx++; | 1291 | q_idx++; |
1276 | continue; | 1292 | continue; |
1277 | } | 1293 | } |
1278 | if (!tc_qdisc_dump_ignore(q) && | 1294 | if (!tc_qdisc_dump_ignore(q) && |
1279 | tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, | 1295 | tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, |
1280 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) | 1296 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) |
1281 | goto done; | 1297 | goto done; |
@@ -1356,7 +1372,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1356 | u32 qid = TC_H_MAJ(clid); | 1372 | u32 qid = TC_H_MAJ(clid); |
1357 | int err; | 1373 | int err; |
1358 | 1374 | ||
1359 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1375 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
1376 | if (!dev) | ||
1360 | return -ENODEV; | 1377 | return -ENODEV; |
1361 | 1378 | ||
1362 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1379 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1391,9 +1408,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1391 | qid = dev->qdisc->handle; | 1408 | qid = dev->qdisc->handle; |
1392 | 1409 | ||
1393 | /* Now qid is genuine qdisc handle consistent | 1410 | /* Now qid is genuine qdisc handle consistent |
1394 | both with parent and child. | 1411 | * both with parent and child. |
1395 | 1412 | * | |
1396 | TC_H_MAJ(pid) still may be unspecified, complete it now. | 1413 | * TC_H_MAJ(pid) still may be unspecified, complete it now. |
1397 | */ | 1414 | */ |
1398 | if (pid) | 1415 | if (pid) |
1399 | pid = TC_H_MAKE(qid, pid); | 1416 | pid = TC_H_MAKE(qid, pid); |
@@ -1403,7 +1420,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1403 | } | 1420 | } |
1404 | 1421 | ||
1405 | /* OK. Locate qdisc */ | 1422 | /* OK. Locate qdisc */ |
1406 | if ((q = qdisc_lookup(dev, qid)) == NULL) | 1423 | q = qdisc_lookup(dev, qid); |
1424 | if (!q) | ||
1407 | return -ENOENT; | 1425 | return -ENOENT; |
1408 | 1426 | ||
1409 | /* An check that it supports classes */ | 1427 | /* An check that it supports classes */ |
@@ -1423,13 +1441,14 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1423 | 1441 | ||
1424 | if (cl == 0) { | 1442 | if (cl == 0) { |
1425 | err = -ENOENT; | 1443 | err = -ENOENT; |
1426 | if (n->nlmsg_type != RTM_NEWTCLASS || !(n->nlmsg_flags&NLM_F_CREATE)) | 1444 | if (n->nlmsg_type != RTM_NEWTCLASS || |
1445 | !(n->nlmsg_flags & NLM_F_CREATE)) | ||
1427 | goto out; | 1446 | goto out; |
1428 | } else { | 1447 | } else { |
1429 | switch (n->nlmsg_type) { | 1448 | switch (n->nlmsg_type) { |
1430 | case RTM_NEWTCLASS: | 1449 | case RTM_NEWTCLASS: |
1431 | err = -EEXIST; | 1450 | err = -EEXIST; |
1432 | if (n->nlmsg_flags&NLM_F_EXCL) | 1451 | if (n->nlmsg_flags & NLM_F_EXCL) |
1433 | goto out; | 1452 | goto out; |
1434 | break; | 1453 | break; |
1435 | case RTM_DELTCLASS: | 1454 | case RTM_DELTCLASS: |
@@ -1521,14 +1540,14 @@ static int tclass_notify(struct net *net, struct sk_buff *oskb, | |||
1521 | return -EINVAL; | 1540 | return -EINVAL; |
1522 | } | 1541 | } |
1523 | 1542 | ||
1524 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1543 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
1544 | n->nlmsg_flags & NLM_F_ECHO); | ||
1525 | } | 1545 | } |
1526 | 1546 | ||
1527 | struct qdisc_dump_args | 1547 | struct qdisc_dump_args { |
1528 | { | 1548 | struct qdisc_walker w; |
1529 | struct qdisc_walker w; | 1549 | struct sk_buff *skb; |
1530 | struct sk_buff *skb; | 1550 | struct netlink_callback *cb; |
1531 | struct netlink_callback *cb; | ||
1532 | }; | 1551 | }; |
1533 | 1552 | ||
1534 | static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg) | 1553 | static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg) |
@@ -1590,7 +1609,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, | |||
1590 | 1609 | ||
1591 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | 1610 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) |
1592 | { | 1611 | { |
1593 | struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh); | 1612 | struct tcmsg *tcm = (struct tcmsg *)NLMSG_DATA(cb->nlh); |
1594 | struct net *net = sock_net(skb->sk); | 1613 | struct net *net = sock_net(skb->sk); |
1595 | struct netdev_queue *dev_queue; | 1614 | struct netdev_queue *dev_queue; |
1596 | struct net_device *dev; | 1615 | struct net_device *dev; |
@@ -1598,7 +1617,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1598 | 1617 | ||
1599 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 1618 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
1600 | return 0; | 1619 | return 0; |
1601 | if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1620 | dev = dev_get_by_index(net, tcm->tcm_ifindex); |
1621 | if (!dev) | ||
1602 | return 0; | 1622 | return 0; |
1603 | 1623 | ||
1604 | s_t = cb->args[0]; | 1624 | s_t = cb->args[0]; |
@@ -1621,19 +1641,22 @@ done: | |||
1621 | } | 1641 | } |
1622 | 1642 | ||
1623 | /* Main classifier routine: scans classifier chain attached | 1643 | /* Main classifier routine: scans classifier chain attached |
1624 | to this qdisc, (optionally) tests for protocol and asks | 1644 | * to this qdisc, (optionally) tests for protocol and asks |
1625 | specific classifiers. | 1645 | * specific classifiers. |
1626 | */ | 1646 | */ |
1627 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | 1647 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, |
1628 | struct tcf_result *res) | 1648 | struct tcf_result *res) |
1629 | { | 1649 | { |
1630 | __be16 protocol = skb->protocol; | 1650 | __be16 protocol = skb->protocol; |
1631 | int err = 0; | 1651 | int err; |
1632 | 1652 | ||
1633 | for (; tp; tp = tp->next) { | 1653 | for (; tp; tp = tp->next) { |
1634 | if ((tp->protocol == protocol || | 1654 | if (tp->protocol != protocol && |
1635 | tp->protocol == htons(ETH_P_ALL)) && | 1655 | tp->protocol != htons(ETH_P_ALL)) |
1636 | (err = tp->classify(skb, tp, res)) >= 0) { | 1656 | continue; |
1657 | err = tp->classify(skb, tp, res); | ||
1658 | |||
1659 | if (err >= 0) { | ||
1637 | #ifdef CONFIG_NET_CLS_ACT | 1660 | #ifdef CONFIG_NET_CLS_ACT |
1638 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) | 1661 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) |
1639 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); | 1662 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); |
@@ -1649,12 +1672,12 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
1649 | struct tcf_result *res) | 1672 | struct tcf_result *res) |
1650 | { | 1673 | { |
1651 | int err = 0; | 1674 | int err = 0; |
1652 | __be16 protocol; | ||
1653 | #ifdef CONFIG_NET_CLS_ACT | 1675 | #ifdef CONFIG_NET_CLS_ACT |
1676 | __be16 protocol; | ||
1654 | struct tcf_proto *otp = tp; | 1677 | struct tcf_proto *otp = tp; |
1655 | reclassify: | 1678 | reclassify: |
1656 | #endif | ||
1657 | protocol = skb->protocol; | 1679 | protocol = skb->protocol; |
1680 | #endif | ||
1658 | 1681 | ||
1659 | err = tc_classify_compat(skb, tp, res); | 1682 | err = tc_classify_compat(skb, tp, res); |
1660 | #ifdef CONFIG_NET_CLS_ACT | 1683 | #ifdef CONFIG_NET_CLS_ACT |
@@ -1664,11 +1687,11 @@ reclassify: | |||
1664 | 1687 | ||
1665 | if (verd++ >= MAX_REC_LOOP) { | 1688 | if (verd++ >= MAX_REC_LOOP) { |
1666 | if (net_ratelimit()) | 1689 | if (net_ratelimit()) |
1667 | printk(KERN_NOTICE | 1690 | pr_notice("%s: packet reclassify loop" |
1668 | "%s: packet reclassify loop" | ||
1669 | " rule prio %u protocol %02x\n", | 1691 | " rule prio %u protocol %02x\n", |
1670 | tp->q->ops->id, | 1692 | tp->q->ops->id, |
1671 | tp->prio & 0xffff, ntohs(tp->protocol)); | 1693 | tp->prio & 0xffff, |
1694 | ntohs(tp->protocol)); | ||
1672 | return TC_ACT_SHOT; | 1695 | return TC_ACT_SHOT; |
1673 | } | 1696 | } |
1674 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | 1697 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); |
@@ -1761,7 +1784,7 @@ static int __init pktsched_init(void) | |||
1761 | 1784 | ||
1762 | err = register_pernet_subsys(&psched_net_ops); | 1785 | err = register_pernet_subsys(&psched_net_ops); |
1763 | if (err) { | 1786 | if (err) { |
1764 | printk(KERN_ERR "pktsched_init: " | 1787 | pr_err("pktsched_init: " |
1765 | "cannot initialize per netns operations\n"); | 1788 | "cannot initialize per netns operations\n"); |
1766 | return err; | 1789 | return err; |
1767 | } | 1790 | } |