From 860cef60fa5db837a14dc3bf675d1e2d58157eb8 Mon Sep 17 00:00:00 2001 From: Bhuvan Mital Date: Thu, 15 Dec 2022 16:46:14 +0000 Subject: [PATCH] rule action implemented in rx/tx nodes --- src/plugins/udps/udps_node.c | 107 +++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 6 deletions(-) diff --git a/src/plugins/udps/udps_node.c b/src/plugins/udps/udps_node.c index 1ec565d72223..508061deb552 100644 --- a/src/plugins/udps/udps_node.c +++ b/src/plugins/udps/udps_node.c @@ -1,8 +1,11 @@ #include "udps_includes.h" #define foreach_udps_rx_error \ - _(UDPS_RX, "UDPS_RX outgoing packets") \ - _(DROP, "UDPS_RX drops") + _(UDPS_RX, "UDPS outgoing packets") \ + _(RULE_MATCHED, "Rule matched on intf") \ + _(RULE_ACTION_FOUND, "Rule action found") \ + _(VALID_OUT_PORT, "Out port rewritten") \ + _(DROP, "UDPS drop pkt") typedef enum { @@ -19,8 +22,11 @@ static char *udps_rx_error_strings[] = { }; #define foreach_udps_tx_error \ - _(UDPS_TX, "UDPS_TX outgoing packets") \ - _(DROP, "UDPS_TX drops") + _(UDPS_TX, "UDPS outgoing packets") \ + _(RULE_MATCHED, "Rule matched on intf") \ + _(RULE_ACTION_FOUND, "Rule action found") \ + _(VALID_OUT_PORT, "Out port rewritten") \ + _(DROP, "UDPS drop pkt") typedef enum { @@ -74,7 +80,59 @@ udps_node_policy_remove(u32 sw_if_index, u8 is_rx) 0, 0, 0); } } +void +udps_apply_rule_action (vlib_main_t *vm, + vlib_buffer_t * b, + udps_rule_action_t *ra, + bool is_rx) +{ + u32 offset, len; + u8 *write_ptr; + /* rewrite the out_port and be done with this */ + if (ra->out_port != UDPS_NO_PORT) { + vnet_buffer (b)->sw_if_index[VLIB_TX] = ra->out_port; + } + + /* loop through all the rewrite actions and apply them one by one */ + for (int i = 0; i < vec_len(ra->rewrite); i++) { + switch(ra->rewrite[i].oper) { + case UDPS_REWRITE_INSERT: + offset = ra->rewrite[i].offset; + len = ra->rewrite[i].len; + vlib_buffer_advance(b, offset); + vlib_buffer_move(vm, b, (len + offset)); + /* alter pkt len and rewind current_data*/ + b->current_length += len; + b->current_data -= len; + write_ptr = vlib_buffer_get_current (b); + clib_memcpy_fast (write_ptr, (u8 *)ra->rewrite[i].value, len); + /*rewind to start of l2 header again*/ + vlib_buffer_advance(b, -offset); + break; + case UDPS_REWRITE_REPLACE: + offset = ra->rewrite[i].offset; + len = ra->rewrite[i].len; + vlib_buffer_advance(b, offset); + write_ptr = vlib_buffer_get_current (b); + clib_memcpy_fast (write_ptr, (u8 *)ra->rewrite[i].value, len); + /*rewind to start of l2 header again*/ + vlib_buffer_advance(b, -offset); + break; + case UDPS_REWRITE_REMOVE: + offset = ra->rewrite[i].offset; + len = ra->rewrite[i].len; + vlib_buffer_advance(b, len+offset); + vlib_buffer_move(vm, b, offset); + /*rewind to start of l2 header again*/ + vlib_buffer_advance(b, -offset); + break; + default: + break; + } + } + return; +} VLIB_NODE_FN (udps_rx_node) (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) @@ -100,6 +158,8 @@ VLIB_NODE_FN (udps_rx_node) (vlib_main_t *vm, vlib_buffer_t *b0; u32 next0; u32 sw_if_index0; + u8 *eth; + udps_rule_action_t *ra = NULL; /* speculatively enqueue b0 to the current next frame */ bi0 = from[0]; @@ -116,9 +176,23 @@ VLIB_NODE_FN (udps_rx_node) (vlib_main_t *vm, /* Determine the next node */ next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; // is this correct ?? - // Do the business logic + /* Do the business logic */ counter[UDPS_RX_ERROR_UDPS_RX]++; - + + eth = (u8 *)vlib_buffer_get_current (b0); + if (udps_db_rule_match(sw_if_index0, true, eth, + vlib_buffer_length_in_chain(vm, b0),&ra)) { + counter[UDPS_RX_ERROR_RULE_MATCHED]++; + if (ra) { + counter[UDPS_RX_ERROR_RULE_ACTION_FOUND]++; + /* apply Rule action on b(0) */ + udps_apply_rule_action(vm, b0, ra, true); + if (ra->out_port != UDPS_NO_PORT) { + counter[UDPS_RX_ERROR_VALID_OUT_PORT]++; + } + } + } + /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, @@ -166,6 +240,10 @@ VLIB_NODE_FN (udps_tx_node) (vlib_main_t *vm, vlib_buffer_t *b0; u32 next0; u32 sw_if_index0; + vnet_sw_interface_t *tx_parent_intf; + vnet_main_t *vnm = vnet_get_main (); + u8 *eth; + udps_rule_action_t *ra = NULL; /* speculatively enqueue b0 to the current next frame */ bi0 = from[0]; @@ -178,10 +256,27 @@ VLIB_NODE_FN (udps_tx_node) (vlib_main_t *vm, b0 = vlib_get_buffer (vm, bi0); sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX]; + tx_parent_intf = vnet_get_sup_sw_interface (vnm, sw_if_index0); + + sw_if_index0 = tx_parent_intf->sw_if_index; /* Determine the next node */ next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; // is this correct ?? + eth = (u8 *)vlib_buffer_get_current (b0); + if (udps_db_rule_match(sw_if_index0, false, eth, + vlib_buffer_length_in_chain(vm, b0),&ra)) { + counter[UDPS_TX_ERROR_RULE_MATCHED]++; + if (ra) { + counter[UDPS_TX_ERROR_RULE_ACTION_FOUND]++; + /* apply Rule action on b(0) */ + udps_apply_rule_action(vm, b0, ra, false); + if (ra->out_port != UDPS_NO_PORT) { + counter[UDPS_TX_ERROR_VALID_OUT_PORT]++; + } + } + } + // Do the business logic counter[UDPS_TX_ERROR_UDPS_TX]++;