diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 65561ebb489e..ab141d49bb9d 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -526,6 +526,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
526 | struct vport *input_vport; | 526 | struct vport *input_vport; |
527 | int len; | 527 | int len; |
528 | int err; | 528 | int err; |
529 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | ||
529 | 530 | ||
530 | err = -EINVAL; | 531 | err = -EINVAL; |
531 | if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] || | 532 | if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] || |
@@ -559,12 +560,12 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
559 | goto err_kfree_skb; | 560 | goto err_kfree_skb; |
560 | 561 | ||
561 | err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet, | 562 | err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet, |
562 | &flow->key); | 563 | &flow->key, log); |
563 | if (err) | 564 | if (err) |
564 | goto err_flow_free; | 565 | goto err_flow_free; |
565 | 566 | ||
566 | err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], | 567 | err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], |
567 | &flow->key, &acts); | 568 | &flow->key, &acts, log); |
568 | if (err) | 569 | if (err) |
569 | goto err_flow_free; | 570 | goto err_flow_free; |
570 | 571 | ||
@@ -855,15 +856,16 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
855 | struct sw_flow_actions *acts; | 856 | struct sw_flow_actions *acts; |
856 | struct sw_flow_match match; | 857 | struct sw_flow_match match; |
857 | int error; | 858 | int error; |
859 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | ||
858 | 860 | ||
859 | /* Must have key and actions. */ | 861 | /* Must have key and actions. */ |
860 | error = -EINVAL; | 862 | error = -EINVAL; |
861 | if (!a[OVS_FLOW_ATTR_KEY]) { | 863 | if (!a[OVS_FLOW_ATTR_KEY]) { |
862 | OVS_NLERR("Flow key attribute not present in new flow.\n"); | 864 | OVS_NLERR(log, "Flow key attr not present in new flow."); |
863 | goto error; | 865 | goto error; |
864 | } | 866 | } |
865 | if (!a[OVS_FLOW_ATTR_ACTIONS]) { | 867 | if (!a[OVS_FLOW_ATTR_ACTIONS]) { |
866 | OVS_NLERR("Flow actions attribute not present in new flow.\n"); | 868 | OVS_NLERR(log, "Flow actions attr not present in new flow."); |
867 | goto error; | 869 | goto error; |
868 | } | 870 | } |
869 | 871 | ||
@@ -878,8 +880,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
878 | 880 | ||
879 | /* Extract key. */ | 881 | /* Extract key. */ |
880 | ovs_match_init(&match, &new_flow->unmasked_key, &mask); | 882 | ovs_match_init(&match, &new_flow->unmasked_key, &mask); |
881 | error = ovs_nla_get_match(&match, | 883 | error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], |
882 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); | 884 | a[OVS_FLOW_ATTR_MASK], log); |
883 | if (error) | 885 | if (error) |
884 | goto err_kfree_flow; | 886 | goto err_kfree_flow; |
885 | 887 | ||
@@ -887,9 +889,9 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
887 | 889 | ||
888 | /* Validate actions. */ | 890 | /* Validate actions. */ |
889 | error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key, | 891 | error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key, |
890 | &acts); | 892 | &acts, log); |
891 | if (error) { | 893 | if (error) { |
892 | OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); | 894 | OVS_NLERR(log, "Flow actions may not be safe on all matching packets."); |
893 | goto err_kfree_flow; | 895 | goto err_kfree_flow; |
894 | } | 896 | } |
895 | 897 | ||
@@ -942,6 +944,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
942 | } | 944 | } |
943 | /* The unmasked key has to be the same for flow updates. */ | 945 | /* The unmasked key has to be the same for flow updates. */ |
944 | if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) { | 946 | if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) { |
947 | /* Look for any overlapping flow. */ | ||
945 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); | 948 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); |
946 | if (!flow) { | 949 | if (!flow) { |
947 | error = -ENOENT; | 950 | error = -ENOENT; |
@@ -984,16 +987,18 @@ error: | |||
984 | /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */ | 987 | /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */ |
985 | static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, | 988 | static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, |
986 | const struct sw_flow_key *key, | 989 | const struct sw_flow_key *key, |
987 | const struct sw_flow_mask *mask) | 990 | const struct sw_flow_mask *mask, |
991 | bool log) | ||
988 | { | 992 | { |
989 | struct sw_flow_actions *acts; | 993 | struct sw_flow_actions *acts; |
990 | struct sw_flow_key masked_key; | 994 | struct sw_flow_key masked_key; |
991 | int error; | 995 | int error; |
992 | 996 | ||
993 | ovs_flow_mask_key(&masked_key, key, mask); | 997 | ovs_flow_mask_key(&masked_key, key, mask); |
994 | error = ovs_nla_copy_actions(a, &masked_key, &acts); | 998 | error = ovs_nla_copy_actions(a, &masked_key, &acts, log); |
995 | if (error) { | 999 | if (error) { |
996 | OVS_NLERR("Actions may not be safe on all matching packets.\n"); | 1000 | OVS_NLERR(log, |
1001 | "Actions may not be safe on all matching packets"); | ||
997 | return ERR_PTR(error); | 1002 | return ERR_PTR(error); |
998 | } | 1003 | } |
999 | 1004 | ||
@@ -1012,23 +1017,25 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1012 | struct sw_flow_actions *old_acts = NULL, *acts = NULL; | 1017 | struct sw_flow_actions *old_acts = NULL, *acts = NULL; |
1013 | struct sw_flow_match match; | 1018 | struct sw_flow_match match; |
1014 | int error; | 1019 | int error; |
1020 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | ||
1015 | 1021 | ||
1016 | /* Extract key. */ | 1022 | /* Extract key. */ |
1017 | error = -EINVAL; | 1023 | error = -EINVAL; |
1018 | if (!a[OVS_FLOW_ATTR_KEY]) { | 1024 | if (!a[OVS_FLOW_ATTR_KEY]) { |
1019 | OVS_NLERR("Flow key attribute not present in set flow.\n"); | 1025 | OVS_NLERR(log, "Flow key attribute not present in set flow."); |
1020 | goto error; | 1026 | goto error; |
1021 | } | 1027 | } |
1022 | 1028 | ||
1023 | ovs_match_init(&match, &key, &mask); | 1029 | ovs_match_init(&match, &key, &mask); |
1024 | error = ovs_nla_get_match(&match, | 1030 | error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], |
1025 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); | 1031 | a[OVS_FLOW_ATTR_MASK], log); |
1026 | if (error) | 1032 | if (error) |
1027 | goto error; | 1033 | goto error; |
1028 | 1034 | ||
1029 | /* Validate actions. */ | 1035 | /* Validate actions. */ |
1030 | if (a[OVS_FLOW_ATTR_ACTIONS]) { | 1036 | if (a[OVS_FLOW_ATTR_ACTIONS]) { |
1031 | acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask); | 1037 | acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask, |
1038 | log); | ||
1032 | if (IS_ERR(acts)) { | 1039 | if (IS_ERR(acts)) { |
1033 | error = PTR_ERR(acts); | 1040 | error = PTR_ERR(acts); |
1034 | goto error; | 1041 | goto error; |
@@ -1109,14 +1116,16 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1109 | struct datapath *dp; | 1116 | struct datapath *dp; |
1110 | struct sw_flow_match match; | 1117 | struct sw_flow_match match; |
1111 | int err; | 1118 | int err; |
1119 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | ||
1112 | 1120 | ||
1113 | if (!a[OVS_FLOW_ATTR_KEY]) { | 1121 | if (!a[OVS_FLOW_ATTR_KEY]) { |
1114 | OVS_NLERR("Flow get message rejected, Key attribute missing.\n"); | 1122 | OVS_NLERR(log, |
1123 | "Flow get message rejected, Key attribute missing."); | ||
1115 | return -EINVAL; | 1124 | return -EINVAL; |
1116 | } | 1125 | } |
1117 | 1126 | ||
1118 | ovs_match_init(&match, &key, NULL); | 1127 | ovs_match_init(&match, &key, NULL); |
1119 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); | 1128 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, log); |
1120 | if (err) | 1129 | if (err) |
1121 | return err; | 1130 | return err; |
1122 | 1131 | ||
@@ -1157,10 +1166,12 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1157 | struct datapath *dp; | 1166 | struct datapath *dp; |
1158 | struct sw_flow_match match; | 1167 | struct sw_flow_match match; |
1159 | int err; | 1168 | int err; |
1169 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | ||
1160 | 1170 | ||
1161 | if (likely(a[OVS_FLOW_ATTR_KEY])) { | 1171 | if (likely(a[OVS_FLOW_ATTR_KEY])) { |
1162 | ovs_match_init(&match, &key, NULL); | 1172 | ovs_match_init(&match, &key, NULL); |
1163 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); | 1173 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, |
1174 | log); | ||
1164 | if (unlikely(err)) | 1175 | if (unlikely(err)) |
1165 | return err; | 1176 | return err; |
1166 | } | 1177 | } |
@@ -1250,8 +1261,10 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1250 | 1261 | ||
1251 | static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = { | 1262 | static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = { |
1252 | [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED }, | 1263 | [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED }, |
1264 | [OVS_FLOW_ATTR_MASK] = { .type = NLA_NESTED }, | ||
1253 | [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED }, | 1265 | [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED }, |
1254 | [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, | 1266 | [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, |
1267 | [OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG }, | ||
1255 | }; | 1268 | }; |
1256 | 1269 | ||
1257 | static const struct genl_ops dp_flow_genl_ops[] = { | 1270 | static const struct genl_ops dp_flow_genl_ops[] = { |