summaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorAlexander Aring <aring@mojatatu.com>2018-02-15 10:54:55 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-16 16:05:02 -0500
commit84ae017a00776486390e2c0cceb4f717c3f809c1 (patch)
tree3233b84f257ba3fccf40ef1b03b075f8084b1c57 /net/sched
parentaea0d727899140820a631bac78f36e9d9ef15ef6 (diff)
net: sched: act: handle generic action errors
This patch adds extack support for generic act handling. The extack will be set deeper to each called function which is not part of netdev core api. Based on work by David Ahern <dsahern@gmail.com> Cc: David Ahern <dsahern@gmail.com> Signed-off-by: Alexander Aring <aring@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_api.c93
1 files changed, 61 insertions, 32 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 662574646256..8e77ddd9f0ad 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -617,31 +617,40 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
617 int err; 617 int err;
618 618
619 if (name == NULL) { 619 if (name == NULL) {
620 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); 620 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
621 if (err < 0) 621 if (err < 0)
622 goto err_out; 622 goto err_out;
623 err = -EINVAL; 623 err = -EINVAL;
624 kind = tb[TCA_ACT_KIND]; 624 kind = tb[TCA_ACT_KIND];
625 if (!kind) 625 if (!kind) {
626 NL_SET_ERR_MSG(extack, "TC action kind must be specified");
626 goto err_out; 627 goto err_out;
627 if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) 628 }
629 if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
630 NL_SET_ERR_MSG(extack, "TC action name too long");
628 goto err_out; 631 goto err_out;
632 }
629 if (tb[TCA_ACT_COOKIE]) { 633 if (tb[TCA_ACT_COOKIE]) {
630 int cklen = nla_len(tb[TCA_ACT_COOKIE]); 634 int cklen = nla_len(tb[TCA_ACT_COOKIE]);
631 635
632 if (cklen > TC_COOKIE_MAX_SIZE) 636 if (cklen > TC_COOKIE_MAX_SIZE) {
637 NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
633 goto err_out; 638 goto err_out;
639 }
634 640
635 cookie = nla_memdup_cookie(tb); 641 cookie = nla_memdup_cookie(tb);
636 if (!cookie) { 642 if (!cookie) {
643 NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
637 err = -ENOMEM; 644 err = -ENOMEM;
638 goto err_out; 645 goto err_out;
639 } 646 }
640 } 647 }
641 } else { 648 } else {
642 err = -EINVAL; 649 if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
643 if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) 650 NL_SET_ERR_MSG(extack, "TC action name too long");
651 err = -EINVAL;
644 goto err_out; 652 goto err_out;
653 }
645 } 654 }
646 655
647 a_o = tc_lookup_action_n(act_name); 656 a_o = tc_lookup_action_n(act_name);
@@ -664,6 +673,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
664 goto err_mod; 673 goto err_mod;
665 } 674 }
666#endif 675#endif
676 NL_SET_ERR_MSG(extack, "Failed to load TC action module");
667 err = -ENOENT; 677 err = -ENOENT;
668 goto err_out; 678 goto err_out;
669 } 679 }
@@ -698,6 +708,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
698 708
699 list_add_tail(&a->list, &actions); 709 list_add_tail(&a->list, &actions);
700 tcf_action_destroy(&actions, bind); 710 tcf_action_destroy(&actions, bind);
711 NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
701 return ERR_PTR(err); 712 return ERR_PTR(err);
702 } 713 }
703 } 714 }
@@ -734,7 +745,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
734 int err; 745 int err;
735 int i; 746 int i;
736 747
737 err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL); 748 err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
738 if (err < 0) 749 if (err < 0)
739 return err; 750 return err;
740 751
@@ -842,7 +853,8 @@ out_nlmsg_trim:
842 853
843static int 854static int
844tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, 855tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
845 struct list_head *actions, int event) 856 struct list_head *actions, int event,
857 struct netlink_ext_ack *extack)
846{ 858{
847 struct sk_buff *skb; 859 struct sk_buff *skb;
848 860
@@ -851,6 +863,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
851 return -ENOBUFS; 863 return -ENOBUFS;
852 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event, 864 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
853 0, 0) <= 0) { 865 0, 0) <= 0) {
866 NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
854 kfree_skb(skb); 867 kfree_skb(skb);
855 return -EINVAL; 868 return -EINVAL;
856 } 869 }
@@ -859,7 +872,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
859} 872}
860 873
861static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, 874static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
862 struct nlmsghdr *n, u32 portid) 875 struct nlmsghdr *n, u32 portid,
876 struct netlink_ext_ack *extack)
863{ 877{
864 struct nlattr *tb[TCA_ACT_MAX + 1]; 878 struct nlattr *tb[TCA_ACT_MAX + 1];
865 const struct tc_action_ops *ops; 879 const struct tc_action_ops *ops;
@@ -867,20 +881,24 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
867 int index; 881 int index;
868 int err; 882 int err;
869 883
870 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); 884 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
871 if (err < 0) 885 if (err < 0)
872 goto err_out; 886 goto err_out;
873 887
874 err = -EINVAL; 888 err = -EINVAL;
875 if (tb[TCA_ACT_INDEX] == NULL || 889 if (tb[TCA_ACT_INDEX] == NULL ||
876 nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) 890 nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
891 NL_SET_ERR_MSG(extack, "Invalid TC action index value");
877 goto err_out; 892 goto err_out;
893 }
878 index = nla_get_u32(tb[TCA_ACT_INDEX]); 894 index = nla_get_u32(tb[TCA_ACT_INDEX]);
879 895
880 err = -EINVAL; 896 err = -EINVAL;
881 ops = tc_lookup_action(tb[TCA_ACT_KIND]); 897 ops = tc_lookup_action(tb[TCA_ACT_KIND]);
882 if (!ops) /* could happen in batch of actions */ 898 if (!ops) { /* could happen in batch of actions */
899 NL_SET_ERR_MSG(extack, "Specified TC action not found");
883 goto err_out; 900 goto err_out;
901 }
884 err = -ENOENT; 902 err = -ENOENT;
885 if (ops->lookup(net, &a, index) == 0) 903 if (ops->lookup(net, &a, index) == 0)
886 goto err_mod; 904 goto err_mod;
@@ -895,7 +913,8 @@ err_out:
895} 913}
896 914
897static int tca_action_flush(struct net *net, struct nlattr *nla, 915static int tca_action_flush(struct net *net, struct nlattr *nla,
898 struct nlmsghdr *n, u32 portid) 916 struct nlmsghdr *n, u32 portid,
917 struct netlink_ext_ack *extack)
899{ 918{
900 struct sk_buff *skb; 919 struct sk_buff *skb;
901 unsigned char *b; 920 unsigned char *b;
@@ -909,35 +928,39 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
909 int err = -ENOMEM; 928 int err = -ENOMEM;
910 929
911 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 930 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
912 if (!skb) { 931 if (!skb)
913 pr_debug("tca_action_flush: failed skb alloc\n");
914 return err; 932 return err;
915 }
916 933
917 b = skb_tail_pointer(skb); 934 b = skb_tail_pointer(skb);
918 935
919 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); 936 err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
920 if (err < 0) 937 if (err < 0)
921 goto err_out; 938 goto err_out;
922 939
923 err = -EINVAL; 940 err = -EINVAL;
924 kind = tb[TCA_ACT_KIND]; 941 kind = tb[TCA_ACT_KIND];
925 ops = tc_lookup_action(kind); 942 ops = tc_lookup_action(kind);
926 if (!ops) /*some idjot trying to flush unknown action */ 943 if (!ops) { /*some idjot trying to flush unknown action */
944 NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
927 goto err_out; 945 goto err_out;
946 }
928 947
929 nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, 948 nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
930 sizeof(*t), 0); 949 sizeof(*t), 0);
931 if (!nlh) 950 if (!nlh) {
951 NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
932 goto out_module_put; 952 goto out_module_put;
953 }
933 t = nlmsg_data(nlh); 954 t = nlmsg_data(nlh);
934 t->tca_family = AF_UNSPEC; 955 t->tca_family = AF_UNSPEC;
935 t->tca__pad1 = 0; 956 t->tca__pad1 = 0;
936 t->tca__pad2 = 0; 957 t->tca__pad2 = 0;
937 958
938 nest = nla_nest_start(skb, TCA_ACT_TAB); 959 nest = nla_nest_start(skb, TCA_ACT_TAB);
939 if (!nest) 960 if (!nest) {
961 NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
940 goto out_module_put; 962 goto out_module_put;
963 }
941 964
942 err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops); 965 err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops);
943 if (err <= 0) { 966 if (err <= 0) {
@@ -954,6 +977,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
954 n->nlmsg_flags & NLM_F_ECHO); 977 n->nlmsg_flags & NLM_F_ECHO);
955 if (err > 0) 978 if (err > 0)
956 return 0; 979 return 0;
980 if (err < 0)
981 NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
957 982
958 return err; 983 return err;
959 984
@@ -966,7 +991,7 @@ err_out:
966 991
967static int 992static int
968tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, 993tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
969 u32 portid) 994 u32 portid, struct netlink_ext_ack *extack)
970{ 995{
971 int ret; 996 int ret;
972 struct sk_buff *skb; 997 struct sk_buff *skb;
@@ -977,6 +1002,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
977 1002
978 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION, 1003 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
979 0, 1) <= 0) { 1004 0, 1) <= 0) {
1005 NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
980 kfree_skb(skb); 1006 kfree_skb(skb);
981 return -EINVAL; 1007 return -EINVAL;
982 } 1008 }
@@ -984,6 +1010,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
984 /* now do the delete */ 1010 /* now do the delete */
985 ret = tcf_action_destroy(actions, 0); 1011 ret = tcf_action_destroy(actions, 0);
986 if (ret < 0) { 1012 if (ret < 0) {
1013 NL_SET_ERR_MSG(extack, "Failed to delete TC action");
987 kfree_skb(skb); 1014 kfree_skb(skb);
988 return ret; 1015 return ret;
989 } 1016 }
@@ -997,26 +1024,27 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
997 1024
998static int 1025static int
999tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, 1026tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1000 u32 portid, int event) 1027 u32 portid, int event, struct netlink_ext_ack *extack)
1001{ 1028{
1002 int i, ret; 1029 int i, ret;
1003 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; 1030 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
1004 struct tc_action *act; 1031 struct tc_action *act;
1005 LIST_HEAD(actions); 1032 LIST_HEAD(actions);
1006 1033
1007 ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL); 1034 ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1008 if (ret < 0) 1035 if (ret < 0)
1009 return ret; 1036 return ret;
1010 1037
1011 if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) { 1038 if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
1012 if (tb[1]) 1039 if (tb[1])
1013 return tca_action_flush(net, tb[1], n, portid); 1040 return tca_action_flush(net, tb[1], n, portid, extack);
1014 1041
1042 NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
1015 return -EINVAL; 1043 return -EINVAL;
1016 } 1044 }
1017 1045
1018 for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { 1046 for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1019 act = tcf_action_get_1(net, tb[i], n, portid); 1047 act = tcf_action_get_1(net, tb[i], n, portid, extack);
1020 if (IS_ERR(act)) { 1048 if (IS_ERR(act)) {
1021 ret = PTR_ERR(act); 1049 ret = PTR_ERR(act);
1022 goto err; 1050 goto err;
@@ -1026,9 +1054,9 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1026 } 1054 }
1027 1055
1028 if (event == RTM_GETACTION) 1056 if (event == RTM_GETACTION)
1029 ret = tcf_get_notify(net, portid, n, &actions, event); 1057 ret = tcf_get_notify(net, portid, n, &actions, event, extack);
1030 else { /* delete */ 1058 else { /* delete */
1031 ret = tcf_del_notify(net, n, &actions, portid); 1059 ret = tcf_del_notify(net, n, &actions, portid, extack);
1032 if (ret) 1060 if (ret)
1033 goto err; 1061 goto err;
1034 return ret; 1062 return ret;
@@ -1041,7 +1069,7 @@ err:
1041 1069
1042static int 1070static int
1043tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, 1071tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
1044 u32 portid) 1072 u32 portid, struct netlink_ext_ack *extack)
1045{ 1073{
1046 struct sk_buff *skb; 1074 struct sk_buff *skb;
1047 int err = 0; 1075 int err = 0;
@@ -1052,6 +1080,7 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
1052 1080
1053 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags, 1081 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
1054 RTM_NEWACTION, 0, 0) <= 0) { 1082 RTM_NEWACTION, 0, 0) <= 0) {
1083 NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while deleting TC action");
1055 kfree_skb(skb); 1084 kfree_skb(skb);
1056 return -EINVAL; 1085 return -EINVAL;
1057 } 1086 }
@@ -1075,7 +1104,7 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
1075 if (ret) 1104 if (ret)
1076 return ret; 1105 return ret;
1077 1106
1078 return tcf_add_notify(net, n, &actions, portid); 1107 return tcf_add_notify(net, n, &actions, portid, extack);
1079} 1108}
1080 1109
1081static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON; 1110static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
@@ -1103,7 +1132,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
1103 return ret; 1132 return ret;
1104 1133
1105 if (tca[TCA_ACT_TAB] == NULL) { 1134 if (tca[TCA_ACT_TAB] == NULL) {
1106 pr_notice("tc_ctl_action: received NO action attribs\n"); 1135 NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
1107 return -EINVAL; 1136 return -EINVAL;
1108 } 1137 }
1109 1138
@@ -1126,11 +1155,11 @@ replay:
1126 break; 1155 break;
1127 case RTM_DELACTION: 1156 case RTM_DELACTION:
1128 ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, 1157 ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1129 portid, RTM_DELACTION); 1158 portid, RTM_DELACTION, extack);
1130 break; 1159 break;
1131 case RTM_GETACTION: 1160 case RTM_GETACTION:
1132 ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, 1161 ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1133 portid, RTM_GETACTION); 1162 portid, RTM_GETACTION, extack);
1134 break; 1163 break;
1135 default: 1164 default:
1136 BUG(); 1165 BUG();