diff options
-rw-r--r-- | src/plugins/dpdk/device/flow.c | 70 | ||||
-rw-r--r-- | src/vnet/flow/flow.h | 8 | ||||
-rw-r--r-- | src/vnet/flow/flow_cli.c | 17 |
3 files changed, 91 insertions, 4 deletions
diff --git a/src/plugins/dpdk/device/flow.c b/src/plugins/dpdk/device/flow.c index c20da251884..d3ca4359722 100644 --- a/src/plugins/dpdk/device/flow.c +++ b/src/plugins/dpdk/device/flow.c @@ -28,12 +28,39 @@ #include <dpdk/device/dpdk_priv.h> #include <vppinfra/error.h> +/* check if flow is L2 flow */ +#define FLOW_IS_L2_LAYER(f) \ + (f->type == VNET_FLOW_TYPE_ETHERNET) + +/* check if flow is L4 type */ +#define FLOW_IS_L4_LAYER(f) \ + ((f->type == VNET_FLOW_TYPE_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP6_N_TUPLE)) + +/* check if flow is L4 tunnel type */ +#define FLOW_IS_L4_TUNNEL_LAYER(f) \ + ((f->type >= VNET_FLOW_TYPE_IP4_VXLAN) || \ + (f->type <= VNET_FLOW_TYPE_IP6_GTPU_IP6)) + /* constant structs */ static const struct rte_flow_attr ingress = {.ingress = 1 }; +static inline bool +mac_address_is_all_zero (const u8 addr[6]) +{ + int i = 0; + + for (i = 0; i < 6; i++) + if (addr[i] != 0) + return false; + + return true; +} + static int dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) { + struct rte_flow_item_eth eth[2] = { }; struct rte_flow_item_ipv4 ip4[2] = { }; struct rte_flow_item_ipv4 inner_ip4[2] = { }; struct rte_flow_item_ipv6 ip6[2] = { }; @@ -70,8 +97,42 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) /* Ethernet */ vec_add2 (items, item, 1); item->type = RTE_FLOW_ITEM_TYPE_ETH; - item->spec = NULL; - item->mask = NULL; + if (f->type == VNET_FLOW_TYPE_ETHERNET) + { + vnet_flow_ethernet_t *te = &f->ethernet; + + clib_memset (ð[0], 0, sizeof (eth[0])); + clib_memset (ð[1], 0, sizeof (eth[1])); + + /* check if SMAC/DMAC/Ether_type assigned */ + if (!mac_address_is_all_zero (te->eth_hdr.dst_address)) + { + clib_memcpy_fast (ð[0].dst, &te->eth_hdr.dst_address, + sizeof (eth[0].dst)); + clib_memset (ð[1].dst, 0xFF, sizeof (eth[1].dst)); + } + + if (!mac_address_is_all_zero (te->eth_hdr.src_address)) + { + clib_memcpy_fast (ð[0].src, &te->eth_hdr.src_address, + sizeof (eth[0].src)); + clib_memset (ð[1].src, 0xFF, sizeof (eth[1].src)); + } + + if (te->eth_hdr.type) + { + eth[0].type = clib_host_to_net_u16 (te->eth_hdr.type); + eth[1].type = clib_host_to_net_u16 (0xFFFF); + } + + item->spec = eth; + item->mask = eth + 1; + } + else + { + item->spec = NULL; + item->mask = NULL; + } /* VLAN */ if ((f->type == VNET_FLOW_TYPE_IP4_N_TUPLE) || @@ -83,6 +144,9 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) item->mask = NULL; } + if (FLOW_IS_L2_LAYER (f)) + goto pattern_end; + /* IP */ vec_add2 (items, item, 1); if ((f->type == VNET_FLOW_TYPE_IP6_N_TUPLE) || @@ -420,6 +484,7 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) } } +pattern_end: vec_add2 (items, item, 1); item->type = RTE_FLOW_ITEM_TYPE_END; @@ -578,6 +643,7 @@ dpdk_flow_ops_fn (vnet_main_t * vnm, vnet_flow_dev_op_t op, u32 dev_instance, switch (flow->type) { + case VNET_FLOW_TYPE_ETHERNET: case VNET_FLOW_TYPE_IP4_N_TUPLE: case VNET_FLOW_TYPE_IP6_N_TUPLE: case VNET_FLOW_TYPE_IP4_VXLAN: diff --git a/src/vnet/flow/flow.h b/src/vnet/flow/flow.h index c0aa9119ce1..5def01a08ef 100644 --- a/src/vnet/flow/flow.h +++ b/src/vnet/flow/flow.h @@ -21,10 +21,15 @@ #include <vnet/l3_types.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> +#include <vnet/ethernet/packet.h> #define foreach_flow_type \ + /* l2 flow*/ \ + _(ETHERNET, ethernet, "ethernet") \ + /* l4 flow*/ \ _(IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \ _(IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \ + /* L4 tunnel flow*/ \ _(IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \ _(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \ _(IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \ @@ -36,6 +41,9 @@ _(IP6_GTPU_IP4, ip6_gtpu_ip4, "ipv6-gtpu-ipv4") \ _(IP6_GTPU_IP6, ip6_gtpu_ip6, "ipv6-gtpu-ipv6") +#define foreach_flow_entry_ethernet \ + _fe(ethernet_header_t, eth_hdr) + #define foreach_flow_entry_ip4_n_tuple \ _fe(ip4_address_and_mask_t, src_addr) \ _fe(ip4_address_and_mask_t, dst_addr) \ diff --git a/src/vnet/flow/flow_cli.c b/src/vnet/flow/flow_cli.c index 1c09b2b6149..500f16b883b 100644 --- a/src/vnet/flow/flow_cli.c +++ b/src/vnet/flow/flow_cli.c @@ -294,6 +294,8 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, ip6_address_and_mask_t inner_ip6d = { }; ip_port_and_mask_t sport = { }; ip_port_and_mask_t dport = { }; + u16 eth_type; + bool ethernet_set = false; clib_memset (&flow, 0, sizeof (vnet_flow_t)); flow.index = ~0; @@ -312,6 +314,9 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, action = FLOW_ENABLE; else if (unformat (line_input, "disable")) action = FLOW_DISABLE; + else if (unformat (line_input, "eth-type %U", + unformat_ethernet_type_host_byte_order, ð_type)) + ethernet_set = true; else if (unformat (line_input, "src-ip %U", unformat_ip4_address_and_mask, &ip4s)) outer_ip4_set = true; @@ -336,7 +341,6 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "inner-ip6-dst-ip %U", unformat_ip6_address_and_mask, &inner_ip6d)) inner_ip6_set = true; - else if (unformat (line_input, "src-port %U", unformat_ip_port_and_mask, &sport)) ; @@ -390,6 +394,8 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, return clib_error_return (0, "Please specify at least one action"); /* Adjust the flow type */ + if (ethernet_set == true) + outer_type = VNET_FLOW_TYPE_ETHERNET; if (outer_ip4_set == true) outer_type = VNET_FLOW_TYPE_IP4_N_TUPLE; else if (outer_ip6_set == true) @@ -402,7 +408,9 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, if (outer_type == VNET_FLOW_TYPE_UNKNOWN) return clib_error_return (0, "Please specify a supported flow type"); - if (outer_type == VNET_FLOW_TYPE_IP4_N_TUPLE) + if (outer_type == VNET_FLOW_TYPE_ETHERNET) + type = VNET_FLOW_TYPE_ETHERNET; + else if (outer_type == VNET_FLOW_TYPE_IP4_N_TUPLE) { type = VNET_FLOW_TYPE_IP4_N_TUPLE; @@ -450,6 +458,11 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, //assign specific field values per flow type switch (type) { + case VNET_FLOW_TYPE_ETHERNET: + memset (&flow.ethernet, 0, sizeof (flow.ethernet)); + flow.ethernet.eth_hdr.type = eth_type; + break; + case VNET_FLOW_TYPE_IP4_N_TUPLE: case VNET_FLOW_TYPE_IP4_GTPC: case VNET_FLOW_TYPE_IP4_GTPU: |