@@ -60,6 +60,89 @@ static struct ch_tc_pedit_fields pedits[] = {
6060 PEDIT_FIELDS (IP6_ , DST_127_96 , 4 , nat_lip , 12 ),
6161};
6262
63+ static const struct cxgb4_natmode_config cxgb4_natmode_config_array [] = {
64+ /* Default supported NAT modes */
65+ {
66+ .chip = CHELSIO_T5 ,
67+ .flags = CXGB4_ACTION_NATMODE_NONE ,
68+ .natmode = NAT_MODE_NONE ,
69+ },
70+ {
71+ .chip = CHELSIO_T5 ,
72+ .flags = CXGB4_ACTION_NATMODE_DIP ,
73+ .natmode = NAT_MODE_DIP ,
74+ },
75+ {
76+ .chip = CHELSIO_T5 ,
77+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT ,
78+ .natmode = NAT_MODE_DIP_DP ,
79+ },
80+ {
81+ .chip = CHELSIO_T5 ,
82+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT |
83+ CXGB4_ACTION_NATMODE_SIP ,
84+ .natmode = NAT_MODE_DIP_DP_SIP ,
85+ },
86+ {
87+ .chip = CHELSIO_T5 ,
88+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT |
89+ CXGB4_ACTION_NATMODE_SPORT ,
90+ .natmode = NAT_MODE_DIP_DP_SP ,
91+ },
92+ {
93+ .chip = CHELSIO_T5 ,
94+ .flags = CXGB4_ACTION_NATMODE_SIP | CXGB4_ACTION_NATMODE_SPORT ,
95+ .natmode = NAT_MODE_SIP_SP ,
96+ },
97+ {
98+ .chip = CHELSIO_T5 ,
99+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP |
100+ CXGB4_ACTION_NATMODE_SPORT ,
101+ .natmode = NAT_MODE_DIP_SIP_SP ,
102+ },
103+ {
104+ .chip = CHELSIO_T5 ,
105+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP |
106+ CXGB4_ACTION_NATMODE_DPORT |
107+ CXGB4_ACTION_NATMODE_SPORT ,
108+ .natmode = NAT_MODE_ALL ,
109+ },
110+ /* T6+ can ignore L4 ports when they're disabled. */
111+ {
112+ .chip = CHELSIO_T6 ,
113+ .flags = CXGB4_ACTION_NATMODE_SIP ,
114+ .natmode = NAT_MODE_SIP_SP ,
115+ },
116+ {
117+ .chip = CHELSIO_T6 ,
118+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SPORT ,
119+ .natmode = NAT_MODE_DIP_DP_SP ,
120+ },
121+ {
122+ .chip = CHELSIO_T6 ,
123+ .flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP ,
124+ .natmode = NAT_MODE_ALL ,
125+ },
126+ };
127+
128+ static void cxgb4_action_natmode_tweak (struct ch_filter_specification * fs ,
129+ u8 natmode_flags )
130+ {
131+ u8 i = 0 ;
132+
133+ /* Translate the enabled NAT 4-tuple fields to one of the
134+ * hardware supported NAT mode configurations. This ensures
135+ * that we pick a valid combination, where the disabled fields
136+ * do not get overwritten to 0.
137+ */
138+ for (i = 0 ; i < ARRAY_SIZE (cxgb4_natmode_config_array ); i ++ ) {
139+ if (cxgb4_natmode_config_array [i ].flags == natmode_flags ) {
140+ fs -> nat_mode = cxgb4_natmode_config_array [i ].natmode ;
141+ return ;
142+ }
143+ }
144+ }
145+
63146static struct ch_tc_flower_entry * allocate_flower_entry (void )
64147{
65148 struct ch_tc_flower_entry * new = kzalloc (sizeof (* new ), GFP_KERNEL );
@@ -289,7 +372,8 @@ static void offload_pedit(struct ch_filter_specification *fs, u32 val, u32 mask,
289372}
290373
291374static void process_pedit_field (struct ch_filter_specification * fs , u32 val ,
292- u32 mask , u32 offset , u8 htype )
375+ u32 mask , u32 offset , u8 htype ,
376+ u8 * natmode_flags )
293377{
294378 switch (htype ) {
295379 case FLOW_ACT_MANGLE_HDR_TYPE_ETH :
@@ -314,67 +398,102 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
314398 switch (offset ) {
315399 case PEDIT_IP4_SRC :
316400 offload_pedit (fs , val , mask , IP4_SRC );
401+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
317402 break ;
318403 case PEDIT_IP4_DST :
319404 offload_pedit (fs , val , mask , IP4_DST );
405+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
320406 }
321- fs -> nat_mode = NAT_MODE_ALL ;
322407 break ;
323408 case FLOW_ACT_MANGLE_HDR_TYPE_IP6 :
324409 switch (offset ) {
325410 case PEDIT_IP6_SRC_31_0 :
326411 offload_pedit (fs , val , mask , IP6_SRC_31_0 );
412+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
327413 break ;
328414 case PEDIT_IP6_SRC_63_32 :
329415 offload_pedit (fs , val , mask , IP6_SRC_63_32 );
416+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
330417 break ;
331418 case PEDIT_IP6_SRC_95_64 :
332419 offload_pedit (fs , val , mask , IP6_SRC_95_64 );
420+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
333421 break ;
334422 case PEDIT_IP6_SRC_127_96 :
335423 offload_pedit (fs , val , mask , IP6_SRC_127_96 );
424+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
336425 break ;
337426 case PEDIT_IP6_DST_31_0 :
338427 offload_pedit (fs , val , mask , IP6_DST_31_0 );
428+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
339429 break ;
340430 case PEDIT_IP6_DST_63_32 :
341431 offload_pedit (fs , val , mask , IP6_DST_63_32 );
432+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
342433 break ;
343434 case PEDIT_IP6_DST_95_64 :
344435 offload_pedit (fs , val , mask , IP6_DST_95_64 );
436+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
345437 break ;
346438 case PEDIT_IP6_DST_127_96 :
347439 offload_pedit (fs , val , mask , IP6_DST_127_96 );
440+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
348441 }
349- fs -> nat_mode = NAT_MODE_ALL ;
350442 break ;
351443 case FLOW_ACT_MANGLE_HDR_TYPE_TCP :
352444 switch (offset ) {
353445 case PEDIT_TCP_SPORT_DPORT :
354- if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
446+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK ) {
355447 fs -> nat_fport = val ;
356- else
448+ * natmode_flags |= CXGB4_ACTION_NATMODE_SPORT ;
449+ } else {
357450 fs -> nat_lport = val >> 16 ;
451+ * natmode_flags |= CXGB4_ACTION_NATMODE_DPORT ;
452+ }
358453 }
359- fs -> nat_mode = NAT_MODE_ALL ;
360454 break ;
361455 case FLOW_ACT_MANGLE_HDR_TYPE_UDP :
362456 switch (offset ) {
363457 case PEDIT_UDP_SPORT_DPORT :
364- if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
458+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK ) {
365459 fs -> nat_fport = val ;
366- else
460+ * natmode_flags |= CXGB4_ACTION_NATMODE_SPORT ;
461+ } else {
367462 fs -> nat_lport = val >> 16 ;
463+ * natmode_flags |= CXGB4_ACTION_NATMODE_DPORT ;
464+ }
368465 }
369- fs -> nat_mode = NAT_MODE_ALL ;
466+ break ;
467+ }
468+ }
469+
470+ static int cxgb4_action_natmode_validate (struct adapter * adap , u8 natmode_flags ,
471+ struct netlink_ext_ack * extack )
472+ {
473+ u8 i = 0 ;
474+
475+ /* Extract the NAT mode to enable based on what 4-tuple fields
476+ * are enabled to be overwritten. This ensures that the
477+ * disabled fields don't get overwritten to 0.
478+ */
479+ for (i = 0 ; i < ARRAY_SIZE (cxgb4_natmode_config_array ); i ++ ) {
480+ const struct cxgb4_natmode_config * c ;
481+
482+ c = & cxgb4_natmode_config_array [i ];
483+ if (CHELSIO_CHIP_VERSION (adap -> params .chip ) >= c -> chip &&
484+ natmode_flags == c -> flags )
485+ return 0 ;
370486 }
487+ NL_SET_ERR_MSG_MOD (extack , "Unsupported NAT mode 4-tuple combination" );
488+ return - EOPNOTSUPP ;
371489}
372490
373491void cxgb4_process_flow_actions (struct net_device * in ,
374492 struct flow_action * actions ,
375493 struct ch_filter_specification * fs )
376494{
377495 struct flow_action_entry * act ;
496+ u8 natmode_flags = 0 ;
378497 int i ;
379498
380499 flow_action_for_each (i , act , actions ) {
@@ -426,7 +545,8 @@ void cxgb4_process_flow_actions(struct net_device *in,
426545 val = act -> mangle .val ;
427546 offset = act -> mangle .offset ;
428547
429- process_pedit_field (fs , val , mask , offset , htype );
548+ process_pedit_field (fs , val , mask , offset , htype ,
549+ & natmode_flags );
430550 }
431551 break ;
432552 case FLOW_ACTION_QUEUE :
@@ -438,6 +558,9 @@ void cxgb4_process_flow_actions(struct net_device *in,
438558 break ;
439559 }
440560 }
561+ if (natmode_flags )
562+ cxgb4_action_natmode_tweak (fs , natmode_flags );
563+
441564}
442565
443566static bool valid_l4_mask (u32 mask )
@@ -454,7 +577,8 @@ static bool valid_l4_mask(u32 mask)
454577}
455578
456579static bool valid_pedit_action (struct net_device * dev ,
457- const struct flow_action_entry * act )
580+ const struct flow_action_entry * act ,
581+ u8 * natmode_flags )
458582{
459583 u32 mask , offset ;
460584 u8 htype ;
@@ -479,7 +603,10 @@ static bool valid_pedit_action(struct net_device *dev,
479603 case FLOW_ACT_MANGLE_HDR_TYPE_IP4 :
480604 switch (offset ) {
481605 case PEDIT_IP4_SRC :
606+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
607+ break ;
482608 case PEDIT_IP4_DST :
609+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
483610 break ;
484611 default :
485612 netdev_err (dev , "%s: Unsupported pedit field\n" ,
@@ -493,10 +620,13 @@ static bool valid_pedit_action(struct net_device *dev,
493620 case PEDIT_IP6_SRC_63_32 :
494621 case PEDIT_IP6_SRC_95_64 :
495622 case PEDIT_IP6_SRC_127_96 :
623+ * natmode_flags |= CXGB4_ACTION_NATMODE_SIP ;
624+ break ;
496625 case PEDIT_IP6_DST_31_0 :
497626 case PEDIT_IP6_DST_63_32 :
498627 case PEDIT_IP6_DST_95_64 :
499628 case PEDIT_IP6_DST_127_96 :
629+ * natmode_flags |= CXGB4_ACTION_NATMODE_DIP ;
500630 break ;
501631 default :
502632 netdev_err (dev , "%s: Unsupported pedit field\n" ,
@@ -512,6 +642,10 @@ static bool valid_pedit_action(struct net_device *dev,
512642 __func__ );
513643 return false;
514644 }
645+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
646+ * natmode_flags |= CXGB4_ACTION_NATMODE_SPORT ;
647+ else
648+ * natmode_flags |= CXGB4_ACTION_NATMODE_DPORT ;
515649 break ;
516650 default :
517651 netdev_err (dev , "%s: Unsupported pedit field\n" ,
@@ -527,6 +661,10 @@ static bool valid_pedit_action(struct net_device *dev,
527661 __func__ );
528662 return false;
529663 }
664+ if (~mask & PEDIT_TCP_UDP_SPORT_MASK )
665+ * natmode_flags |= CXGB4_ACTION_NATMODE_SPORT ;
666+ else
667+ * natmode_flags |= CXGB4_ACTION_NATMODE_DPORT ;
530668 break ;
531669 default :
532670 netdev_err (dev , "%s: Unsupported pedit field\n" ,
@@ -546,10 +684,12 @@ int cxgb4_validate_flow_actions(struct net_device *dev,
546684 struct netlink_ext_ack * extack ,
547685 u8 matchall_filter )
548686{
687+ struct adapter * adap = netdev2adap (dev );
549688 struct flow_action_entry * act ;
550689 bool act_redir = false;
551690 bool act_pedit = false;
552691 bool act_vlan = false;
692+ u8 natmode_flags = 0 ;
553693 int i ;
554694
555695 if (!flow_action_basic_hw_stats_check (actions , extack ))
@@ -563,7 +703,6 @@ int cxgb4_validate_flow_actions(struct net_device *dev,
563703 break ;
564704 case FLOW_ACTION_MIRRED :
565705 case FLOW_ACTION_REDIRECT : {
566- struct adapter * adap = netdev2adap (dev );
567706 struct net_device * n_dev , * target_dev ;
568707 bool found = false;
569708 unsigned int i ;
@@ -620,7 +759,8 @@ int cxgb4_validate_flow_actions(struct net_device *dev,
620759 }
621760 break ;
622761 case FLOW_ACTION_MANGLE : {
623- bool pedit_valid = valid_pedit_action (dev , act );
762+ bool pedit_valid = valid_pedit_action (dev , act ,
763+ & natmode_flags );
624764
625765 if (!pedit_valid )
626766 return - EOPNOTSUPP ;
@@ -642,6 +782,15 @@ int cxgb4_validate_flow_actions(struct net_device *dev,
642782 return - EINVAL ;
643783 }
644784
785+ if (act_pedit ) {
786+ int ret ;
787+
788+ ret = cxgb4_action_natmode_validate (adap , natmode_flags ,
789+ extack );
790+ if (ret )
791+ return ret ;
792+ }
793+
645794 return 0 ;
646795}
647796
0 commit comments