X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fflow%2Fflow_cli.c;h=500f16b883bf1453aa996b32c379b6246596b2e0;hb=4ff8d615caf992a643abe7506f289c499de10d5c;hp=11f3bcfad97bb847233569b0dd06c8828fff2aae;hpb=a35cc14d37466f0737fa928d25697fbfe6e7d657;p=vpp.git diff --git a/src/vnet/flow/flow_cli.c b/src/vnet/flow/flow_cli.c index 11f3bcfad97..500f16b883b 100644 --- a/src/vnet/flow/flow_cli.c +++ b/src/vnet/flow/flow_cli.c @@ -90,6 +90,30 @@ format_flow_actions (u8 * s, va_list * args) return s; } +u8 * +format_flow_enabled_hw (u8 * s, va_list * args) +{ + u32 flow_index = va_arg (*args, u32); + vnet_flow_t *f = vnet_get_flow (flow_index); + if (f == 0) + return format (s, "not found"); + + u8 *t = 0; + u32 hw_if_index; + uword private_data; + vnet_main_t *vnm = vnet_get_main (); + /* *INDENT-OFF* */ + hash_foreach (hw_if_index, private_data, f->private_data, + ({ + t = format (t, "%s%U", t ? ", " : "", + format_vnet_hw_if_index_name, vnm, hw_if_index); + })); + /* *INDENT-ON* */ + s = format (s, "%v", t); + vec_free (t); + return s; +} + static const char *flow_type_strings[] = { 0, #define _(a,b,c) c, foreach_flow_type @@ -250,11 +274,30 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, FLOW_ENABLE, FLOW_DISABLE } action = FLOW_UNKNOWN_ACTION; - u32 hw_if_index = ~0, tmp, flow_index = ~0; + u32 hw_if_index = ~0, flow_index = ~0; int rv; - u8 prot; - - memset (&flow, 0, sizeof (vnet_flow_t)); + u32 prot = 0, teid = 0; + vnet_flow_type_t type = VNET_FLOW_TYPE_IP4_N_TUPLE; + bool is_gtpc_set = false; + bool is_gtpu_set = false; + vnet_flow_type_t outer_type = VNET_FLOW_TYPE_UNKNOWN; + vnet_flow_type_t inner_type = VNET_FLOW_TYPE_UNKNOWN; + bool outer_ip4_set = false, inner_ip4_set = false; + bool outer_ip6_set = false, inner_ip6_set = false; + ip4_address_and_mask_t ip4s = { }; + ip4_address_and_mask_t ip4d = { }; + ip4_address_and_mask_t inner_ip4s = { }; + ip4_address_and_mask_t inner_ip4d = { }; + ip6_address_and_mask_t ip6s = { }; + ip6_address_and_mask_t ip6d = { }; + ip6_address_and_mask_t inner_ip6s = { }; + 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; flow.actions = 0; flow.ip4_n_tuple.protocol = ~0; @@ -271,24 +314,47 @@ 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, - &flow.ip4_n_tuple.src_addr)) - ; + unformat_ip4_address_and_mask, &ip4s)) + outer_ip4_set = true; else if (unformat (line_input, "dst-ip %U", - unformat_ip4_address_and_mask, - &flow.ip4_n_tuple.dst_addr)) - ; + unformat_ip4_address_and_mask, &ip4d)) + outer_ip4_set = true; + else if (unformat (line_input, "ip6-src-ip %U", + unformat_ip6_address_and_mask, &ip6s)) + outer_ip6_set = true; + else if (unformat (line_input, "ip6-dst-ip %U", + unformat_ip6_address_and_mask, &ip6d)) + outer_ip6_set = true; + else if (unformat (line_input, "inner-src-ip %U", + unformat_ip4_address_and_mask, &inner_ip4s)) + inner_ip4_set = true; + else if (unformat (line_input, "inner-dst-ip %U", + unformat_ip4_address_and_mask, &inner_ip4d)) + inner_ip4_set = true; + else if (unformat (line_input, "inner-ip6-src-ip %U", + unformat_ip6_address_and_mask, &inner_ip6s)) + inner_ip6_set = true; + 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, - &flow.ip4_n_tuple.src_port)) + &sport)) ; else if (unformat (line_input, "dst-port %U", unformat_ip_port_and_mask, - &flow.ip4_n_tuple.dst_port)) + &dport)) ; else if (unformat (line_input, "proto %U", unformat_ip_protocol, &prot)) - flow.ip4_n_tuple.protocol = prot; - else if (unformat (line_input, "proto %u", &tmp)) - flow.ip4_n_tuple.protocol = tmp; + ; + else if (unformat (line_input, "proto %u", &prot)) + ; + else if (unformat (line_input, "gtpc teid %u", &teid)) + is_gtpc_set = true; + else if (unformat (line_input, "gtpu teid %u", &teid)) + is_gtpu_set = true; else if (unformat (line_input, "index %u", &flow_index)) ; else if (unformat (line_input, "next-node %U", unformat_vlib_node, vm, @@ -299,6 +365,11 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "buffer-advance %d", &flow.buffer_advance)) flow.actions |= VNET_FLOW_ACTION_BUFFER_ADVANCE; + else if (unformat (line_input, "redirect-to-queue %d", + &flow.redirect_queue)) + flow.actions |= VNET_FLOW_ACTION_REDIRECT_TO_QUEUE; + else if (unformat (line_input, "drop")) + flow.actions |= VNET_FLOW_ACTION_DROP; else if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index)) ; @@ -319,13 +390,176 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, switch (action) { case FLOW_ADD: - if (flow.ip4_n_tuple.protocol == (ip_protocol_t) ~ 0) - return clib_error_return (0, "Please specify ip protocol"); - if (flow.actions == 0) return clib_error_return (0, "Please specify at least one action"); - flow.type = VNET_FLOW_TYPE_IP4_N_TUPLE; + + /* 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) + outer_type = VNET_FLOW_TYPE_IP6_N_TUPLE; + if (inner_ip4_set == true) + inner_type = VNET_FLOW_TYPE_IP4_N_TUPLE; + else if (inner_ip6_set == true) + inner_type = VNET_FLOW_TYPE_IP6_N_TUPLE; + + if (outer_type == VNET_FLOW_TYPE_UNKNOWN) + return clib_error_return (0, "Please specify a supported flow type"); + + 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; + + if (inner_type == VNET_FLOW_TYPE_UNKNOWN) + { + if (is_gtpc_set) + type = VNET_FLOW_TYPE_IP4_GTPC; + else if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP4_GTPU; + } + else if (inner_type == VNET_FLOW_TYPE_IP4_N_TUPLE) + { + if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP4_GTPU_IP4; + } + else if (inner_type == VNET_FLOW_TYPE_IP6_N_TUPLE) + { + if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP4_GTPU_IP6; + } + } + else if (outer_type == VNET_FLOW_TYPE_IP6_N_TUPLE) + { + type = VNET_FLOW_TYPE_IP6_N_TUPLE; + + if (inner_type == VNET_FLOW_TYPE_UNKNOWN) + { + if (is_gtpc_set) + type = VNET_FLOW_TYPE_IP6_GTPC; + else if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP6_GTPU; + } + else if (inner_type == VNET_FLOW_TYPE_IP4_N_TUPLE) + { + if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP6_GTPU_IP4; + } + else if (inner_type == VNET_FLOW_TYPE_IP6_N_TUPLE) + { + if (is_gtpu_set) + type = VNET_FLOW_TYPE_IP6_GTPU_IP6; + } + } + + //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: + case VNET_FLOW_TYPE_IP4_GTPU_IP4: + case VNET_FLOW_TYPE_IP4_GTPU_IP6: + clib_memcpy (&flow.ip4_n_tuple.src_addr, &ip4s, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip4_n_tuple.dst_addr, &ip4d, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip4_n_tuple.src_port, &sport, + sizeof (ip_port_and_mask_t)); + clib_memcpy (&flow.ip4_n_tuple.dst_port, &dport, + sizeof (ip_port_and_mask_t)); + flow.ip4_n_tuple.protocol = prot; + + if (type == VNET_FLOW_TYPE_IP4_GTPC) + flow.ip4_gtpc.teid = teid; + else if (type == VNET_FLOW_TYPE_IP4_GTPU) + flow.ip4_gtpu.teid = teid; + else if (type == VNET_FLOW_TYPE_IP4_GTPU_IP4) + { + flow.ip4_gtpu_ip4.teid = teid; + clib_memcpy (&flow.ip4_gtpu_ip4.inner_src_addr, &inner_ip4s, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip4_gtpu_ip4.inner_dst_addr, &inner_ip4d, + sizeof (ip4_address_and_mask_t)); + } + else if (type == VNET_FLOW_TYPE_IP4_GTPU_IP6) + { + flow.ip4_gtpu_ip6.teid = teid; + clib_memcpy (&flow.ip4_gtpu_ip6.inner_src_addr, &inner_ip6s, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip4_gtpu_ip6.inner_dst_addr, &inner_ip6d, + sizeof (ip6_address_and_mask_t)); + } + + if (flow.ip4_n_tuple.protocol == (ip_protocol_t) ~ 0) + return clib_error_return (0, "Please specify ip protocol"); + if ((type != VNET_FLOW_TYPE_IP4_N_TUPLE) && + (flow.ip4_n_tuple.protocol != IP_PROTOCOL_UDP)) + return clib_error_return (0, + "For GTP related flow, ip protocol must be UDP"); + break; + + case VNET_FLOW_TYPE_IP6_N_TUPLE: + case VNET_FLOW_TYPE_IP6_GTPC: + case VNET_FLOW_TYPE_IP6_GTPU: + case VNET_FLOW_TYPE_IP6_GTPU_IP4: + case VNET_FLOW_TYPE_IP6_GTPU_IP6: + clib_memcpy (&flow.ip6_n_tuple.src_addr, &ip6s, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip6_n_tuple.dst_addr, &ip6d, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip6_n_tuple.src_port, &sport, + sizeof (ip_port_and_mask_t)); + clib_memcpy (&flow.ip6_n_tuple.dst_port, &dport, + sizeof (ip_port_and_mask_t)); + flow.ip6_n_tuple.protocol = prot; + + if (type == VNET_FLOW_TYPE_IP6_GTPC) + flow.ip6_gtpc.teid = teid; + else if (type == VNET_FLOW_TYPE_IP6_GTPU) + flow.ip6_gtpu.teid = teid; + else if (type == VNET_FLOW_TYPE_IP6_GTPU_IP4) + { + flow.ip6_gtpu_ip4.teid = teid; + clib_memcpy (&flow.ip6_gtpu_ip4.inner_src_addr, &inner_ip4s, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip6_gtpu_ip4.inner_dst_addr, &inner_ip4d, + sizeof (ip4_address_and_mask_t)); + } + else if (type == VNET_FLOW_TYPE_IP6_GTPU_IP6) + { + flow.ip6_gtpu_ip6.teid = teid; + clib_memcpy (&flow.ip6_gtpu_ip6.inner_src_addr, &inner_ip6s, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip6_gtpu_ip6.inner_dst_addr, &inner_ip6d, + sizeof (ip6_address_and_mask_t)); + } + + if (flow.ip6_n_tuple.protocol == (ip_protocol_t) ~ 0) + return clib_error_return (0, "Please specify ip protocol"); + if ((type != VNET_FLOW_TYPE_IP4_N_TUPLE) && + (flow.ip6_n_tuple.protocol != IP_PROTOCOL_UDP)) + return clib_error_return (0, + "For GTP related flow, ip protocol must be UDP"); + break; + + default: + break; + } + + flow.type = type; rv = vnet_flow_add (vnm, &flow, &flow_index); + if (!rv) + printf ("flow %u added\n", flow_index); + break; case FLOW_DEL: rv = vnet_flow_del (vnm, flow_index);