@@ -47,6 +47,20 @@ struct ch_tc_pedit_fields pedits[] = {
47
47
PEDIT_FIELDS (ETH_ , DMAC_47_32 , 2 , dmac , 4 ),
48
48
PEDIT_FIELDS (ETH_ , SMAC_15_0 , 2 , smac , 0 ),
49
49
PEDIT_FIELDS (ETH_ , SMAC_47_16 , 4 , smac , 2 ),
50
+ PEDIT_FIELDS (IP4_ , SRC , 4 , nat_fip , 0 ),
51
+ PEDIT_FIELDS (IP4_ , DST , 4 , nat_lip , 0 ),
52
+ PEDIT_FIELDS (IP6_ , SRC_31_0 , 4 , nat_fip , 0 ),
53
+ PEDIT_FIELDS (IP6_ , SRC_63_32 , 4 , nat_fip , 4 ),
54
+ PEDIT_FIELDS (IP6_ , SRC_95_64 , 4 , nat_fip , 8 ),
55
+ PEDIT_FIELDS (IP6_ , SRC_127_96 , 4 , nat_fip , 12 ),
56
+ PEDIT_FIELDS (IP6_ , DST_31_0 , 4 , nat_lip , 0 ),
57
+ PEDIT_FIELDS (IP6_ , DST_63_32 , 4 , nat_lip , 4 ),
58
+ PEDIT_FIELDS (IP6_ , DST_95_64 , 4 , nat_lip , 8 ),
59
+ PEDIT_FIELDS (IP6_ , DST_127_96 , 4 , nat_lip , 12 ),
60
+ PEDIT_FIELDS (TCP_ , SPORT , 2 , nat_fport , 0 ),
61
+ PEDIT_FIELDS (TCP_ , DPORT , 2 , nat_lport , 0 ),
62
+ PEDIT_FIELDS (UDP_ , SPORT , 2 , nat_fport , 0 ),
63
+ PEDIT_FIELDS (UDP_ , DPORT , 2 , nat_lport , 0 ),
50
64
};
51
65
52
66
static struct ch_tc_flower_entry * allocate_flower_entry (void )
@@ -121,6 +135,11 @@ static void cxgb4_process_flow_match(struct net_device *dev,
121
135
memcpy (& fs -> val .fip [0 ], & key -> src , sizeof (key -> src ));
122
136
memcpy (& fs -> mask .lip [0 ], & mask -> dst , sizeof (mask -> dst ));
123
137
memcpy (& fs -> mask .fip [0 ], & mask -> src , sizeof (mask -> src ));
138
+
139
+ /* also initialize nat_lip/fip to same values */
140
+ memcpy (& fs -> nat_lip [0 ], & key -> dst , sizeof (key -> dst ));
141
+ memcpy (& fs -> nat_fip [0 ], & key -> src , sizeof (key -> src ));
142
+
124
143
}
125
144
126
145
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS ) {
@@ -138,6 +157,10 @@ static void cxgb4_process_flow_match(struct net_device *dev,
138
157
memcpy (& fs -> val .fip [0 ], key -> src .s6_addr , sizeof (key -> src ));
139
158
memcpy (& fs -> mask .lip [0 ], mask -> dst .s6_addr , sizeof (mask -> dst ));
140
159
memcpy (& fs -> mask .fip [0 ], mask -> src .s6_addr , sizeof (mask -> src ));
160
+
161
+ /* also initialize nat_lip/fip to same values */
162
+ memcpy (& fs -> nat_lip [0 ], key -> dst .s6_addr , sizeof (key -> dst ));
163
+ memcpy (& fs -> nat_fip [0 ], key -> src .s6_addr , sizeof (key -> src ));
141
164
}
142
165
143
166
if (dissector_uses_key (cls -> dissector , FLOW_DISSECTOR_KEY_PORTS )) {
@@ -153,6 +176,10 @@ static void cxgb4_process_flow_match(struct net_device *dev,
153
176
fs -> mask .lport = cpu_to_be16 (mask -> dst );
154
177
fs -> val .fport = cpu_to_be16 (key -> src );
155
178
fs -> mask .fport = cpu_to_be16 (mask -> src );
179
+
180
+ /* also initialize nat_lport/fport to same values */
181
+ fs -> nat_lport = cpu_to_be16 (key -> dst );
182
+ fs -> nat_fport = cpu_to_be16 (key -> src );
156
183
}
157
184
158
185
if (dissector_uses_key (cls -> dissector , FLOW_DISSECTOR_KEY_IP )) {
@@ -301,6 +328,70 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
301
328
fs -> newsmac = 1 ;
302
329
offload_pedit (fs , val , mask , ETH_SMAC_47_16 );
303
330
}
331
+ break ;
332
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
333
+ switch (offset ) {
334
+ case PEDIT_IP4_SRC :
335
+ offload_pedit (fs , val , mask , IP4_SRC );
336
+ break ;
337
+ case PEDIT_IP4_DST :
338
+ offload_pedit (fs , val , mask , IP4_DST );
339
+ }
340
+ fs -> nat_mode = NAT_MODE_ALL ;
341
+ break ;
342
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 :
343
+ switch (offset ) {
344
+ case PEDIT_IP6_SRC_31_0 :
345
+ offload_pedit (fs , val , mask , IP6_SRC_31_0 );
346
+ break ;
347
+ case PEDIT_IP6_SRC_63_32 :
348
+ offload_pedit (fs , val , mask , IP6_SRC_63_32 );
349
+ break ;
350
+ case PEDIT_IP6_SRC_95_64 :
351
+ offload_pedit (fs , val , mask , IP6_SRC_95_64 );
352
+ break ;
353
+ case PEDIT_IP6_SRC_127_96 :
354
+ offload_pedit (fs , val , mask , IP6_SRC_127_96 );
355
+ break ;
356
+ case PEDIT_IP6_DST_31_0 :
357
+ offload_pedit (fs , val , mask , IP6_DST_31_0 );
358
+ break ;
359
+ case PEDIT_IP6_DST_63_32 :
360
+ offload_pedit (fs , val , mask , IP6_DST_63_32 );
361
+ break ;
362
+ case PEDIT_IP6_DST_95_64 :
363
+ offload_pedit (fs , val , mask , IP6_DST_95_64 );
364
+ break ;
365
+ case PEDIT_IP6_DST_127_96 :
366
+ offload_pedit (fs , val , mask , IP6_DST_127_96 );
367
+ }
368
+ fs -> nat_mode = NAT_MODE_ALL ;
369
+ break ;
370
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP :
371
+ switch (offset ) {
372
+ case PEDIT_TCP_SPORT_DPORT :
373
+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
374
+ offload_pedit (fs , cpu_to_be32 (val ) >> 16 ,
375
+ cpu_to_be32 (mask ) >> 16 ,
376
+ TCP_SPORT );
377
+ else
378
+ offload_pedit (fs , cpu_to_be32 (val ),
379
+ cpu_to_be32 (mask ), TCP_DPORT );
380
+ }
381
+ fs -> nat_mode = NAT_MODE_ALL ;
382
+ break ;
383
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP :
384
+ switch (offset ) {
385
+ case PEDIT_UDP_SPORT_DPORT :
386
+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
387
+ offload_pedit (fs , cpu_to_be32 (val ) >> 16 ,
388
+ cpu_to_be32 (mask ) >> 16 ,
389
+ UDP_SPORT );
390
+ else
391
+ offload_pedit (fs , cpu_to_be32 (val ),
392
+ cpu_to_be32 (mask ), UDP_DPORT );
393
+ }
394
+ fs -> nat_mode = NAT_MODE_ALL ;
304
395
}
305
396
}
306
397
@@ -365,6 +456,119 @@ static void cxgb4_process_flow_actions(struct net_device *in,
365
456
}
366
457
}
367
458
459
+ static bool valid_l4_mask (u32 mask )
460
+ {
461
+ u16 hi , lo ;
462
+
463
+ /* Either the upper 16-bits (SPORT) OR the lower
464
+ * 16-bits (DPORT) can be set, but NOT BOTH.
465
+ */
466
+ hi = (mask >> 16 ) & 0xFFFF ;
467
+ lo = mask & 0xFFFF ;
468
+
469
+ return hi && lo ? false : true;
470
+ }
471
+
472
+ static bool valid_pedit_action (struct net_device * dev ,
473
+ const struct tc_action * a )
474
+ {
475
+ u32 mask , offset ;
476
+ u8 cmd , htype ;
477
+ int nkeys , i ;
478
+
479
+ nkeys = tcf_pedit_nkeys (a );
480
+ for (i = 0 ; i < nkeys ; i ++ ) {
481
+ htype = tcf_pedit_htype (a , i );
482
+ cmd = tcf_pedit_cmd (a , i );
483
+ mask = tcf_pedit_mask (a , i );
484
+ offset = tcf_pedit_offset (a , i );
485
+
486
+ if (cmd != TCA_PEDIT_KEY_EX_CMD_SET ) {
487
+ netdev_err (dev , "%s: Unsupported pedit cmd\n" ,
488
+ __func__ );
489
+ return false;
490
+ }
491
+
492
+ switch (htype ) {
493
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH :
494
+ switch (offset ) {
495
+ case PEDIT_ETH_DMAC_31_0 :
496
+ case PEDIT_ETH_DMAC_47_32_SMAC_15_0 :
497
+ case PEDIT_ETH_SMAC_47_16 :
498
+ break ;
499
+ default :
500
+ netdev_err (dev , "%s: Unsupported pedit field\n" ,
501
+ __func__ );
502
+ return false;
503
+ }
504
+ break ;
505
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
506
+ switch (offset ) {
507
+ case PEDIT_IP4_SRC :
508
+ case PEDIT_IP4_DST :
509
+ break ;
510
+ default :
511
+ netdev_err (dev , "%s: Unsupported pedit field\n" ,
512
+ __func__ );
513
+ return false;
514
+ }
515
+ break ;
516
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 :
517
+ switch (offset ) {
518
+ case PEDIT_IP6_SRC_31_0 :
519
+ case PEDIT_IP6_SRC_63_32 :
520
+ case PEDIT_IP6_SRC_95_64 :
521
+ case PEDIT_IP6_SRC_127_96 :
522
+ case PEDIT_IP6_DST_31_0 :
523
+ case PEDIT_IP6_DST_63_32 :
524
+ case PEDIT_IP6_DST_95_64 :
525
+ case PEDIT_IP6_DST_127_96 :
526
+ break ;
527
+ default :
528
+ netdev_err (dev , "%s: Unsupported pedit field\n" ,
529
+ __func__ );
530
+ return false;
531
+ }
532
+ break ;
533
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP :
534
+ switch (offset ) {
535
+ case PEDIT_TCP_SPORT_DPORT :
536
+ if (!valid_l4_mask (~mask )) {
537
+ netdev_err (dev , "%s: Unsupported mask for TCP L4 ports\n" ,
538
+ __func__ );
539
+ return false;
540
+ }
541
+ break ;
542
+ default :
543
+ netdev_err (dev , "%s: Unsupported pedit field\n" ,
544
+ __func__ );
545
+ return false;
546
+ }
547
+ break ;
548
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP :
549
+ switch (offset ) {
550
+ case PEDIT_UDP_SPORT_DPORT :
551
+ if (!valid_l4_mask (~mask )) {
552
+ netdev_err (dev , "%s: Unsupported mask for UDP L4 ports\n" ,
553
+ __func__ );
554
+ return false;
555
+ }
556
+ break ;
557
+ default :
558
+ netdev_err (dev , "%s: Unsupported pedit field\n" ,
559
+ __func__ );
560
+ return false;
561
+ }
562
+ break ;
563
+ default :
564
+ netdev_err (dev , "%s: Unsupported pedit type\n" ,
565
+ __func__ );
566
+ return false;
567
+ }
568
+ }
569
+ return true;
570
+ }
571
+
368
572
static int cxgb4_validate_flow_actions (struct net_device * dev ,
369
573
struct tc_cls_flower_offload * cls )
370
574
{
@@ -426,43 +630,10 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
426
630
}
427
631
act_vlan = true;
428
632
} else if (is_tcf_pedit (a )) {
429
- u32 mask , val , offset ;
430
- u8 cmd , htype ;
431
- int nkeys , i ;
633
+ bool pedit_valid = valid_pedit_action (dev , a );
432
634
433
- nkeys = tcf_pedit_nkeys (a );
434
- for (i = 0 ; i < nkeys ; i ++ ) {
435
- htype = tcf_pedit_htype (a , i );
436
- cmd = tcf_pedit_cmd (a , i );
437
- mask = tcf_pedit_mask (a , i );
438
- val = tcf_pedit_val (a , i );
439
- offset = tcf_pedit_offset (a , i );
440
-
441
- if (cmd != TCA_PEDIT_KEY_EX_CMD_SET ) {
442
- netdev_err (dev , "%s: Unsupported pedit cmd\n" ,
443
- __func__ );
444
- return - EOPNOTSUPP ;
445
- }
446
-
447
- switch (htype ) {
448
- case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH :
449
- switch (offset ) {
450
- case PEDIT_ETH_DMAC_31_0 :
451
- case PEDIT_ETH_DMAC_47_32_SMAC_15_0 :
452
- case PEDIT_ETH_SMAC_47_16 :
453
- break ;
454
- default :
455
- netdev_err (dev , "%s: Unsupported pedit field\n" ,
456
- __func__ );
457
- return - EOPNOTSUPP ;
458
- }
459
- break ;
460
- default :
461
- netdev_err (dev , "%s: Unsupported pedit type\n" ,
462
- __func__ );
463
- return - EOPNOTSUPP ;
464
- }
465
- }
635
+ if (!pedit_valid )
636
+ return - EOPNOTSUPP ;
466
637
act_pedit = true;
467
638
} else {
468
639
netdev_err (dev , "%s: Unsupported action\n" , __func__ );
@@ -503,8 +674,8 @@ int cxgb4_tc_flower_replace(struct net_device *dev,
503
674
504
675
fs = & ch_flower -> fs ;
505
676
fs -> hitcnts = 1 ;
506
- cxgb4_process_flow_actions (dev , cls , fs );
507
677
cxgb4_process_flow_match (dev , cls , fs );
678
+ cxgb4_process_flow_actions (dev , cls , fs );
508
679
509
680
fidx = cxgb4_get_free_ftid (dev , fs -> type ? PF_INET6 : PF_INET );
510
681
if (fidx < 0 ) {
0 commit comments