@@ -114,7 +114,8 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
114114 return 0 ;
115115}
116116
117- /* Key & Mask from the stack comes unaligned in multiple iterations.
117+ /* Key & Mask from the stack comes unaligned in multiple iterations of 4 bytes
118+ * each(u32).
118119 * This routine consolidates such multiple unaligned values into one
119120 * field each for Key & Mask (for src and dst macs separately)
120121 * For example,
@@ -178,14 +179,19 @@ bnxt_fill_l2_rewrite_fields(struct bnxt_tc_actions *actions,
178179
179180static int
180181bnxt_tc_parse_pedit (struct bnxt * bp , struct bnxt_tc_actions * actions ,
181- struct flow_action_entry * act , u8 * eth_addr ,
182+ struct flow_action_entry * act , int act_idx , u8 * eth_addr ,
182183 u8 * eth_addr_mask )
183184{
184- u32 mask , val , offset ;
185+ size_t offset_of_ip6_daddr = offsetof(struct ipv6hdr , daddr );
186+ size_t offset_of_ip6_saddr = offsetof(struct ipv6hdr , saddr );
187+ u32 mask , val , offset , idx ;
185188 u8 htype ;
186189
187190 offset = act -> mangle .offset ;
188191 htype = act -> mangle .htype ;
192+ mask = ~act -> mangle .mask ;
193+ val = act -> mangle .val ;
194+
189195 switch (htype ) {
190196 case FLOW_ACT_MANGLE_HDR_TYPE_ETH :
191197 if (offset > PEDIT_OFFSET_SMAC_LAST_4_BYTES ) {
@@ -195,12 +201,73 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,
195201 return - EINVAL ;
196202 }
197203 actions -> flags |= BNXT_TC_ACTION_FLAG_L2_REWRITE ;
198- mask = ~act -> mangle .mask ;
199- val = act -> mangle .val ;
200204
201205 bnxt_set_l2_key_mask (val , mask , & eth_addr [offset ],
202206 & eth_addr_mask [offset ]);
203207 break ;
208+ case FLOW_ACT_MANGLE_HDR_TYPE_IP4 :
209+ actions -> flags |= BNXT_TC_ACTION_FLAG_NAT_XLATE ;
210+ actions -> nat .l3_is_ipv4 = true;
211+ if (offset == offsetof(struct iphdr , saddr )) {
212+ actions -> nat .src_xlate = true;
213+ actions -> nat .l3 .ipv4 .saddr .s_addr = htonl (val );
214+ } else if (offset == offsetof(struct iphdr , daddr )) {
215+ actions -> nat .src_xlate = false;
216+ actions -> nat .l3 .ipv4 .daddr .s_addr = htonl (val );
217+ } else {
218+ netdev_err (bp -> dev ,
219+ "%s: IPv4_hdr: Invalid pedit field\n" ,
220+ __func__ );
221+ return - EINVAL ;
222+ }
223+
224+ netdev_dbg (bp -> dev , "nat.src_xlate = %d src IP: %pI4 dst ip : %pI4\n" ,
225+ actions -> nat .src_xlate , & actions -> nat .l3 .ipv4 .saddr ,
226+ & actions -> nat .l3 .ipv4 .daddr );
227+ break ;
228+
229+ case FLOW_ACT_MANGLE_HDR_TYPE_IP6 :
230+ actions -> flags |= BNXT_TC_ACTION_FLAG_NAT_XLATE ;
231+ actions -> nat .l3_is_ipv4 = false;
232+ if (offset >= offsetof(struct ipv6hdr , saddr ) &&
233+ offset < offset_of_ip6_daddr ) {
234+ /* 16 byte IPv6 address comes in 4 iterations of
235+ * 4byte chunks each
236+ */
237+ actions -> nat .src_xlate = true;
238+ idx = (offset - offset_of_ip6_saddr ) / 4 ;
239+ /* First 4bytes will be copied to idx 0 and so on */
240+ actions -> nat .l3 .ipv6 .saddr .s6_addr32 [idx ] = htonl (val );
241+ } else if (offset >= offset_of_ip6_daddr &&
242+ offset < offset_of_ip6_daddr + 16 ) {
243+ actions -> nat .src_xlate = false;
244+ idx = (offset - offset_of_ip6_daddr ) / 4 ;
245+ actions -> nat .l3 .ipv6 .saddr .s6_addr32 [idx ] = htonl (val );
246+ } else {
247+ netdev_err (bp -> dev ,
248+ "%s: IPv6_hdr: Invalid pedit field\n" ,
249+ __func__ );
250+ return - EINVAL ;
251+ }
252+ break ;
253+ case FLOW_ACT_MANGLE_HDR_TYPE_TCP :
254+ case FLOW_ACT_MANGLE_HDR_TYPE_UDP :
255+ /* HW does not support L4 rewrite alone without L3
256+ * rewrite
257+ */
258+ if (!(actions -> flags & BNXT_TC_ACTION_FLAG_NAT_XLATE )) {
259+ netdev_err (bp -> dev ,
260+ "Need to specify L3 rewrite as well\n" );
261+ return - EINVAL ;
262+ }
263+ if (actions -> nat .src_xlate )
264+ actions -> nat .l4 .ports .sport = htons (val );
265+ else
266+ actions -> nat .l4 .ports .dport = htons (val );
267+ netdev_dbg (bp -> dev , "actions->nat.sport = %d dport = %d\n" ,
268+ actions -> nat .l4 .ports .sport ,
269+ actions -> nat .l4 .ports .dport );
270+ break ;
204271 default :
205272 netdev_err (bp -> dev , "%s: Unsupported pedit hdr type\n" ,
206273 __func__ );
@@ -258,7 +325,7 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
258325 break ;
259326 /* Packet edit: L2 rewrite, NAT, NAPT */
260327 case FLOW_ACTION_MANGLE :
261- rc = bnxt_tc_parse_pedit (bp , actions , act ,
328+ rc = bnxt_tc_parse_pedit (bp , actions , act , i ,
262329 (u8 * )eth_addr ,
263330 (u8 * )eth_addr_mask );
264331 if (rc )
@@ -533,6 +600,67 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
533600 CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_L2_HEADER_REWRITE ;
534601 }
535602
603+ if (actions -> flags & BNXT_TC_ACTION_FLAG_NAT_XLATE ) {
604+ if (actions -> nat .l3_is_ipv4 ) {
605+ action_flags |=
606+ CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_IPV4_ADDRESS ;
607+
608+ if (actions -> nat .src_xlate ) {
609+ action_flags |=
610+ CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_SRC ;
611+ /* L3 source rewrite */
612+ req .nat_ip_address [0 ] =
613+ actions -> nat .l3 .ipv4 .saddr .s_addr ;
614+ /* L4 source port */
615+ if (actions -> nat .l4 .ports .sport )
616+ req .nat_port =
617+ actions -> nat .l4 .ports .sport ;
618+ } else {
619+ action_flags |=
620+ CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_DEST ;
621+ /* L3 destination rewrite */
622+ req .nat_ip_address [0 ] =
623+ actions -> nat .l3 .ipv4 .daddr .s_addr ;
624+ /* L4 destination port */
625+ if (actions -> nat .l4 .ports .dport )
626+ req .nat_port =
627+ actions -> nat .l4 .ports .dport ;
628+ }
629+ netdev_dbg (bp -> dev ,
630+ "req.nat_ip_address: %pI4 src_xlate: %d req.nat_port: %x\n" ,
631+ req .nat_ip_address , actions -> nat .src_xlate ,
632+ req .nat_port );
633+ } else {
634+ if (actions -> nat .src_xlate ) {
635+ action_flags |=
636+ CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_SRC ;
637+ /* L3 source rewrite */
638+ memcpy (req .nat_ip_address ,
639+ actions -> nat .l3 .ipv6 .saddr .s6_addr32 ,
640+ sizeof (req .nat_ip_address ));
641+ /* L4 source port */
642+ if (actions -> nat .l4 .ports .sport )
643+ req .nat_port =
644+ actions -> nat .l4 .ports .sport ;
645+ } else {
646+ action_flags |=
647+ CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_DEST ;
648+ /* L3 destination rewrite */
649+ memcpy (req .nat_ip_address ,
650+ actions -> nat .l3 .ipv6 .daddr .s6_addr32 ,
651+ sizeof (req .nat_ip_address ));
652+ /* L4 destination port */
653+ if (actions -> nat .l4 .ports .dport )
654+ req .nat_port =
655+ actions -> nat .l4 .ports .dport ;
656+ }
657+ netdev_dbg (bp -> dev ,
658+ "req.nat_ip_address: %pI6 src_xlate: %d req.nat_port: %x\n" ,
659+ req .nat_ip_address , actions -> nat .src_xlate ,
660+ req .nat_port );
661+ }
662+ }
663+
536664 if (actions -> flags & BNXT_TC_ACTION_FLAG_TUNNEL_DECAP ||
537665 actions -> flags & BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP ) {
538666 req .tunnel_handle = tunnel_handle ;
0 commit comments