11#include "udps_includes.h"
22
33#define foreach_udps_rx_error \
4- _(UDPS_RX, "UDPS_RX outgoing packets") \
5- _(DROP, "UDPS_RX drops")
4+ _(UDPS_RX, "UDPS outgoing packets") \
5+ _(RULE_MATCHED, "Rule matched on intf") \
6+ _(RULE_ACTION_FOUND, "Rule action found") \
7+ _(VALID_OUT_PORT, "Out port rewritten") \
8+ _(DROP, "UDPS drop pkt")
69
710typedef enum
811{
@@ -19,8 +22,11 @@ static char *udps_rx_error_strings[] = {
1922};
2023
2124#define foreach_udps_tx_error \
22- _(UDPS_TX, "UDPS_TX outgoing packets") \
23- _(DROP, "UDPS_TX drops")
25+ _(UDPS_TX, "UDPS outgoing packets") \
26+ _(RULE_MATCHED, "Rule matched on intf") \
27+ _(RULE_ACTION_FOUND, "Rule action found") \
28+ _(VALID_OUT_PORT, "Out port rewritten") \
29+ _(DROP, "UDPS drop pkt")
2430
2531typedef enum
2632{
@@ -74,7 +80,59 @@ udps_node_policy_remove(u32 sw_if_index, u8 is_rx)
7480 0 , 0 , 0 );
7581 }
7682}
83+ void
84+ udps_apply_rule_action (vlib_main_t * vm ,
85+ vlib_buffer_t * b ,
86+ udps_rule_action_t * ra ,
87+ bool is_rx )
88+ {
89+ u32 offset , len ;
90+ u8 * write_ptr ;
91+ /* rewrite the out_port and be done with this */
92+ if (ra -> out_port != UDPS_NO_PORT ) {
93+ vnet_buffer (b )-> sw_if_index [VLIB_TX ] = ra -> out_port ;
94+ }
95+
96+ /* loop through all the rewrite actions and apply them one by one */
97+ for (int i = 0 ; i < vec_len (ra -> rewrite ); i ++ ) {
98+ switch (ra -> rewrite [i ].oper ) {
99+ case UDPS_REWRITE_INSERT :
100+ offset = ra -> rewrite [i ].offset ;
101+ len = ra -> rewrite [i ].len ;
102+ vlib_buffer_advance (b , offset );
103+ vlib_buffer_move (vm , b , (len + offset ));
104+ /* alter pkt len and rewind current_data*/
105+ b -> current_length += len ;
106+ b -> current_data -= len ;
107+ write_ptr = vlib_buffer_get_current (b );
108+ clib_memcpy_fast (write_ptr , (u8 * )ra -> rewrite [i ].value , len );
109+ /*rewind to start of l2 header again*/
110+ vlib_buffer_advance (b , - offset );
111+ break ;
112+ case UDPS_REWRITE_REPLACE :
113+ offset = ra -> rewrite [i ].offset ;
114+ len = ra -> rewrite [i ].len ;
115+ vlib_buffer_advance (b , offset );
116+ write_ptr = vlib_buffer_get_current (b );
117+ clib_memcpy_fast (write_ptr , (u8 * )ra -> rewrite [i ].value , len );
118+ /*rewind to start of l2 header again*/
119+ vlib_buffer_advance (b , - offset );
120+ break ;
121+ case UDPS_REWRITE_REMOVE :
122+ offset = ra -> rewrite [i ].offset ;
123+ len = ra -> rewrite [i ].len ;
124+ vlib_buffer_advance (b , len + offset );
125+ vlib_buffer_move (vm , b , offset );
126+ /*rewind to start of l2 header again*/
127+ vlib_buffer_advance (b , - offset );
128+ break ;
129+ default :
130+ break ;
131+ }
132+ }
77133
134+ return ;
135+ }
78136VLIB_NODE_FN (udps_rx_node ) (vlib_main_t * vm ,
79137 vlib_node_runtime_t * node ,
80138 vlib_frame_t * frame )
@@ -100,6 +158,8 @@ VLIB_NODE_FN (udps_rx_node) (vlib_main_t *vm,
100158 vlib_buffer_t * b0 ;
101159 u32 next0 ;
102160 u32 sw_if_index0 ;
161+ u8 * eth ;
162+ udps_rule_action_t * ra = NULL ;
103163
104164 /* speculatively enqueue b0 to the current next frame */
105165 bi0 = from [0 ];
@@ -116,9 +176,23 @@ VLIB_NODE_FN (udps_rx_node) (vlib_main_t *vm,
116176 /* Determine the next node */
117177 next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT ; // is this correct ??
118178
119- // Do the business logic
179+ /* Do the business logic */
120180 counter [UDPS_RX_ERROR_UDPS_RX ]++ ;
121-
181+
182+ eth = (u8 * )vlib_buffer_get_current (b0 );
183+ if (udps_db_rule_match (sw_if_index0 , true, eth ,
184+ vlib_buffer_length_in_chain (vm , b0 ),& ra )) {
185+ counter [UDPS_RX_ERROR_RULE_MATCHED ]++ ;
186+ if (ra ) {
187+ counter [UDPS_RX_ERROR_RULE_ACTION_FOUND ]++ ;
188+ /* apply Rule action on b(0) */
189+ udps_apply_rule_action (vm , b0 , ra , true);
190+ if (ra -> out_port != UDPS_NO_PORT ) {
191+ counter [UDPS_RX_ERROR_VALID_OUT_PORT ]++ ;
192+ }
193+ }
194+ }
195+
122196 /* verify speculative enqueue, maybe switch current next frame */
123197 vlib_validate_buffer_enqueue_x1 (vm , node , next_index ,
124198 to_next , n_left_to_next ,
@@ -166,6 +240,10 @@ VLIB_NODE_FN (udps_tx_node) (vlib_main_t *vm,
166240 vlib_buffer_t * b0 ;
167241 u32 next0 ;
168242 u32 sw_if_index0 ;
243+ vnet_sw_interface_t * tx_parent_intf ;
244+ vnet_main_t * vnm = vnet_get_main ();
245+ u8 * eth ;
246+ udps_rule_action_t * ra = NULL ;
169247
170248 /* speculatively enqueue b0 to the current next frame */
171249 bi0 = from [0 ];
@@ -178,10 +256,27 @@ VLIB_NODE_FN (udps_tx_node) (vlib_main_t *vm,
178256 b0 = vlib_get_buffer (vm , bi0 );
179257
180258 sw_if_index0 = vnet_buffer (b0 )-> sw_if_index [VLIB_TX ];
259+ tx_parent_intf = vnet_get_sup_sw_interface (vnm , sw_if_index0 );
260+
261+ sw_if_index0 = tx_parent_intf -> sw_if_index ;
181262
182263 /* Determine the next node */
183264 next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT ; // is this correct ??
184265
266+ eth = (u8 * )vlib_buffer_get_current (b0 );
267+ if (udps_db_rule_match (sw_if_index0 , false, eth ,
268+ vlib_buffer_length_in_chain (vm , b0 ),& ra )) {
269+ counter [UDPS_TX_ERROR_RULE_MATCHED ]++ ;
270+ if (ra ) {
271+ counter [UDPS_TX_ERROR_RULE_ACTION_FOUND ]++ ;
272+ /* apply Rule action on b(0) */
273+ udps_apply_rule_action (vm , b0 , ra , false);
274+ if (ra -> out_port != UDPS_NO_PORT ) {
275+ counter [UDPS_TX_ERROR_VALID_OUT_PORT ]++ ;
276+ }
277+ }
278+ }
279+
185280 // Do the business logic
186281 counter [UDPS_TX_ERROR_UDPS_TX ]++ ;
187282
0 commit comments