summaryrefslogtreecommitdiffstats
path: root/net/openvswitch/conntrack.c
diff options
context:
space:
mode:
authorJarno Rajahalme <jarno@ovn.org>2017-02-09 14:21:58 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-09 22:59:34 -0500
commit09aa98ad496d6b11a698b258bc64d7f64c55d682 (patch)
treec58988ce19e23909d9e24ab7b0a20a35991c9dda /net/openvswitch/conntrack.c
parent6ffcea79957df43caeaa6d1de5062556a5afc262 (diff)
openvswitch: Inherit master's labels.
We avoid calling into nf_conntrack_in() for expected connections, as that would remove the expectation that we want to stick around until we are ready to commit the connection. Instead, we do a lookup in the expectation table directly. However, after a successful expectation lookup we have set the flow key label field from the master connection, whereas nf_conntrack_in() does not do this. This leads to master's labels being inherited after an expectation lookup, but those labels not being inherited after the corresponding conntrack action with a commit flag. This patch resolves the problem by changing the commit code path to also inherit the master's labels to the expected connection. Resolving this conflict in favor of inheriting the labels allows more information be passed from the master connection to related connections, which would otherwise be much harder if the 32 bits in the connmark are not enough. Labels can still be set explicitly, so this change only affects the default values of the labels in presense of a master connection. Fixes: 7f8a436eaa2c ("openvswitch: Add conntrack action") Signed-off-by: Jarno Rajahalme <jarno@ovn.org> Acked-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Joe Stringer <joe@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch/conntrack.c')
-rw-r--r--net/openvswitch/conntrack.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 7c5bb98c22c6..f989ccf38eab 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -73,6 +73,8 @@ struct ovs_conntrack_info {
73#endif 73#endif
74}; 74};
75 75
76static bool labels_nonzero(const struct ovs_key_ct_labels *labels);
77
76static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info); 78static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
77 79
78static u16 key_to_nfproto(const struct sw_flow_key *key) 80static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -270,18 +272,32 @@ static int ovs_ct_init_labels(struct nf_conn *ct, struct sw_flow_key *key,
270 const struct ovs_key_ct_labels *labels, 272 const struct ovs_key_ct_labels *labels,
271 const struct ovs_key_ct_labels *mask) 273 const struct ovs_key_ct_labels *mask)
272{ 274{
273 struct nf_conn_labels *cl; 275 struct nf_conn_labels *cl, *master_cl;
274 u32 *dst; 276 bool have_mask = labels_nonzero(mask);
275 int i; 277
278 /* Inherit master's labels to the related connection? */
279 master_cl = ct->master ? nf_ct_labels_find(ct->master) : NULL;
280
281 if (!master_cl && !have_mask)
282 return 0; /* Nothing to do. */
276 283
277 cl = ovs_ct_get_conn_labels(ct); 284 cl = ovs_ct_get_conn_labels(ct);
278 if (!cl) 285 if (!cl)
279 return -ENOSPC; 286 return -ENOSPC;
280 287
281 dst = (u32 *)cl->bits; 288 /* Inherit the master's labels, if any. */
282 for (i = 0; i < OVS_CT_LABELS_LEN_32; i++) 289 if (master_cl)
283 dst[i] = (dst[i] & ~mask->ct_labels_32[i]) | 290 *cl = *master_cl;
284 (labels->ct_labels_32[i] & mask->ct_labels_32[i]); 291
292 if (have_mask) {
293 u32 *dst = (u32 *)cl->bits;
294 int i;
295
296 for (i = 0; i < OVS_CT_LABELS_LEN_32; i++)
297 dst[i] = (dst[i] & ~mask->ct_labels_32[i]) |
298 (labels->ct_labels_32[i]
299 & mask->ct_labels_32[i]);
300 }
285 301
286 memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN); 302 memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN);
287 303
@@ -909,13 +925,14 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
909 if (err) 925 if (err)
910 return err; 926 return err;
911 } 927 }
912 if (labels_nonzero(&info->labels.mask)) { 928 if (!nf_ct_is_confirmed(ct)) {
913 if (!nf_ct_is_confirmed(ct)) 929 err = ovs_ct_init_labels(ct, key, &info->labels.value,
914 err = ovs_ct_init_labels(ct, key, &info->labels.value, 930 &info->labels.mask);
915 &info->labels.mask); 931 if (err)
916 else 932 return err;
917 err = ovs_ct_set_labels(ct, key, &info->labels.value, 933 } else if (labels_nonzero(&info->labels.mask)) {
918 &info->labels.mask); 934 err = ovs_ct_set_labels(ct, key, &info->labels.value,
935 &info->labels.mask);
919 if (err) 936 if (err)
920 return err; 937 return err;
921 } 938 }