@@ -227,19 +227,12 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
227
227
return 0 ;
228
228
}
229
229
230
- static int ovs_ct_set_mark (struct sk_buff * skb , struct sw_flow_key * key ,
230
+ static int ovs_ct_set_mark (struct nf_conn * ct , struct sw_flow_key * key ,
231
231
u32 ct_mark , u32 mask )
232
232
{
233
233
#if IS_ENABLED (CONFIG_NF_CONNTRACK_MARK )
234
- enum ip_conntrack_info ctinfo ;
235
- struct nf_conn * ct ;
236
234
u32 new_mark ;
237
235
238
- /* The connection could be invalid, in which case set_mark is no-op. */
239
- ct = nf_ct_get (skb , & ctinfo );
240
- if (!ct )
241
- return 0 ;
242
-
243
236
new_mark = ct_mark | (ct -> mark & ~(mask ));
244
237
if (ct -> mark != new_mark ) {
245
238
ct -> mark = new_mark ;
@@ -254,50 +247,66 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
254
247
#endif
255
248
}
256
249
257
- static int ovs_ct_set_labels (struct sk_buff * skb , struct sw_flow_key * key ,
258
- const struct ovs_key_ct_labels * labels ,
259
- const struct ovs_key_ct_labels * mask )
250
+ static struct nf_conn_labels * ovs_ct_get_conn_labels (struct nf_conn * ct )
260
251
{
261
- enum ip_conntrack_info ctinfo ;
262
252
struct nf_conn_labels * cl ;
263
- struct nf_conn * ct ;
264
-
265
- /* The connection could be invalid, in which case set_label is no-op.*/
266
- ct = nf_ct_get (skb , & ctinfo );
267
- if (!ct )
268
- return 0 ;
269
253
270
254
cl = nf_ct_labels_find (ct );
271
255
if (!cl ) {
272
256
nf_ct_labels_ext_add (ct );
273
257
cl = nf_ct_labels_find (ct );
274
258
}
259
+
260
+ return cl ;
261
+ }
262
+
263
+ /* Initialize labels for a new, yet to be committed conntrack entry. Note that
264
+ * since the new connection is not yet confirmed, and thus no-one else has
265
+ * access to it's labels, we simply write them over. Also, we refrain from
266
+ * triggering events, as receiving change events before the create event would
267
+ * be confusing.
268
+ */
269
+ static int ovs_ct_init_labels (struct nf_conn * ct , struct sw_flow_key * key ,
270
+ const struct ovs_key_ct_labels * labels ,
271
+ const struct ovs_key_ct_labels * mask )
272
+ {
273
+ struct nf_conn_labels * cl ;
274
+ u32 * dst ;
275
+ int i ;
276
+
277
+ cl = ovs_ct_get_conn_labels (ct );
275
278
if (!cl )
276
279
return - ENOSPC ;
277
280
278
- if (nf_ct_is_confirmed (ct )) {
279
- /* Triggers a change event, which makes sense only for
280
- * confirmed connections.
281
- */
282
- int err = nf_connlabels_replace (ct , labels -> ct_labels_32 ,
283
- mask -> ct_labels_32 ,
284
- OVS_CT_LABELS_LEN_32 );
285
- if (err )
286
- return err ;
287
- } else {
288
- u32 * dst = (u32 * )cl -> bits ;
289
- const u32 * msk = mask -> ct_labels_32 ;
290
- const u32 * lbl = labels -> ct_labels_32 ;
291
- int i ;
281
+ dst = (u32 * )cl -> bits ;
282
+ for (i = 0 ; i < OVS_CT_LABELS_LEN_32 ; i ++ )
283
+ dst [i ] = (dst [i ] & ~mask -> ct_labels_32 [i ]) |
284
+ (labels -> ct_labels_32 [i ] & mask -> ct_labels_32 [i ]);
292
285
293
- /* No-one else has access to the non-confirmed entry, copy
294
- * labels over, keeping any bits we are not explicitly setting.
295
- */
296
- for (i = 0 ; i < OVS_CT_LABELS_LEN_32 ; i ++ )
297
- dst [i ] = (dst [i ] & ~msk [i ]) | (lbl [i ] & msk [i ]);
298
- }
286
+ memcpy (& key -> ct .labels , cl -> bits , OVS_CT_LABELS_LEN );
287
+
288
+ return 0 ;
289
+ }
290
+
291
+ static int ovs_ct_set_labels (struct nf_conn * ct , struct sw_flow_key * key ,
292
+ const struct ovs_key_ct_labels * labels ,
293
+ const struct ovs_key_ct_labels * mask )
294
+ {
295
+ struct nf_conn_labels * cl ;
296
+ int err ;
297
+
298
+ cl = ovs_ct_get_conn_labels (ct );
299
+ if (!cl )
300
+ return - ENOSPC ;
301
+
302
+ err = nf_connlabels_replace (ct , labels -> ct_labels_32 ,
303
+ mask -> ct_labels_32 ,
304
+ OVS_CT_LABELS_LEN_32 );
305
+ if (err )
306
+ return err ;
307
+
308
+ memcpy (& key -> ct .labels , cl -> bits , OVS_CT_LABELS_LEN );
299
309
300
- ovs_ct_get_labels (ct , & key -> ct .labels );
301
310
return 0 ;
302
311
}
303
312
@@ -877,25 +886,36 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
877
886
const struct ovs_conntrack_info * info ,
878
887
struct sk_buff * skb )
879
888
{
889
+ enum ip_conntrack_info ctinfo ;
890
+ struct nf_conn * ct ;
880
891
int err ;
881
892
882
893
err = __ovs_ct_lookup (net , key , info , skb );
883
894
if (err )
884
895
return err ;
885
896
897
+ /* The connection could be invalid, in which case this is a no-op.*/
898
+ ct = nf_ct_get (skb , & ctinfo );
899
+ if (!ct )
900
+ return 0 ;
901
+
886
902
/* Apply changes before confirming the connection so that the initial
887
903
* conntrack NEW netlink event carries the values given in the CT
888
904
* action.
889
905
*/
890
906
if (info -> mark .mask ) {
891
- err = ovs_ct_set_mark (skb , key , info -> mark .value ,
907
+ err = ovs_ct_set_mark (ct , key , info -> mark .value ,
892
908
info -> mark .mask );
893
909
if (err )
894
910
return err ;
895
911
}
896
912
if (labels_nonzero (& info -> labels .mask )) {
897
- err = ovs_ct_set_labels (skb , key , & info -> labels .value ,
898
- & info -> labels .mask );
913
+ if (!nf_ct_is_confirmed (ct ))
914
+ err = ovs_ct_init_labels (ct , key , & info -> labels .value ,
915
+ & info -> labels .mask );
916
+ else
917
+ err = ovs_ct_set_labels (ct , key , & info -> labels .value ,
918
+ & info -> labels .mask );
899
919
if (err )
900
920
return err ;
901
921
}
0 commit comments