From 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Dec 2016 23:05:39 +0100 Subject: Reorganize source tree to use single autotools instance Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion --- src/vnet/gre/error.def | 23 ++ src/vnet/gre/gre.api | 57 +++++ src/vnet/gre/gre.c | 455 +++++++++++++++++++++++++++++++++++ src/vnet/gre/gre.h | 235 ++++++++++++++++++ src/vnet/gre/gre_api.c | 204 ++++++++++++++++ src/vnet/gre/interface.c | 606 +++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/gre/node.c | 531 +++++++++++++++++++++++++++++++++++++++++ src/vnet/gre/packet.h | 55 +++++ src/vnet/gre/pg.c | 77 ++++++ 9 files changed, 2243 insertions(+) create mode 100644 src/vnet/gre/error.def create mode 100644 src/vnet/gre/gre.api create mode 100644 src/vnet/gre/gre.c create mode 100644 src/vnet/gre/gre.h create mode 100644 src/vnet/gre/gre_api.c create mode 100644 src/vnet/gre/interface.c create mode 100644 src/vnet/gre/node.c create mode 100644 src/vnet/gre/packet.h create mode 100644 src/vnet/gre/pg.c (limited to 'src/vnet/gre') diff --git a/src/vnet/gre/error.def b/src/vnet/gre/error.def new file mode 100644 index 00000000..161ecc1d --- /dev/null +++ b/src/vnet/gre/error.def @@ -0,0 +1,23 @@ +/* + * gre_error.def: gre errors + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +gre_error (NONE, "no error") +gre_error (UNKNOWN_PROTOCOL, "unknown protocol") +gre_error (UNSUPPORTED_VERSION, "unsupported version") +gre_error (PKTS_DECAP, "GRE input packets decapsulated") +gre_error (PKTS_ENCAP, "GRE output packets encapsulated") +gre_error (NO_SUCH_TUNNEL, "GRE input packets dropped due to missing tunnel") diff --git a/src/vnet/gre/gre.api b/src/vnet/gre/gre.api new file mode 100644 index 00000000..28f6dbc9 --- /dev/null +++ b/src/vnet/gre/gre.api @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define gre_add_del_tunnel +{ + u32 client_index; + u32 context; + u8 is_add; + u8 is_ipv6; + u8 teb; + u8 src_address[16]; + u8 dst_address[16]; + u32 outer_fib_id; +}; + +define gre_add_del_tunnel_reply +{ + u32 context; + i32 retval; + u32 sw_if_index; +}; + +define gre_tunnel_dump +{ + u32 client_index; + u32 context; + u32 sw_if_index; +}; + +define gre_tunnel_details +{ + u32 context; + u32 sw_if_index; + u8 is_ipv6; + u8 teb; + u8 src_address[16]; + u8 dst_address[16]; + u32 outer_fib_id; +}; + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c new file mode 100644 index 00000000..0faed13e --- /dev/null +++ b/src/vnet/gre/gre.c @@ -0,0 +1,455 @@ +/* + * gre.c: gre + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +gre_main_t gre_main; + +typedef struct { + union { + ip4_and_gre_header_t ip4_and_gre; + u64 as_u64[3]; + }; +} ip4_and_gre_union_t; + + +/* Packet trace structure */ +typedef struct { + /* Tunnel-id / index in tunnel vector */ + u32 tunnel_id; + + /* pkt length */ + u32 length; + + /* tunnel ip4 addresses */ + ip4_address_t src; + ip4_address_t dst; +} gre_tx_trace_t; + +u8 * format_gre_tx_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + gre_tx_trace_t * t = va_arg (*args, gre_tx_trace_t *); + + s = format (s, "GRE: tunnel %d len %d src %U dst %U", + t->tunnel_id, clib_net_to_host_u16 (t->length), + format_ip4_address, &t->src.as_u8, + format_ip4_address, &t->dst.as_u8); + return s; +} + +u8 * format_gre_protocol (u8 * s, va_list * args) +{ + gre_protocol_t p = va_arg (*args, u32); + gre_main_t * gm = &gre_main; + gre_protocol_info_t * pi = gre_get_protocol_info (gm, p); + + if (pi) + s = format (s, "%s", pi->name); + else + s = format (s, "0x%04x", p); + + return s; +} + +u8 * format_gre_header_with_length (u8 * s, va_list * args) +{ + gre_main_t * gm = &gre_main; + gre_header_t * h = va_arg (*args, gre_header_t *); + u32 max_header_bytes = va_arg (*args, u32); + gre_protocol_t p = clib_net_to_host_u16 (h->protocol); + uword indent, header_bytes; + + header_bytes = sizeof (h[0]); + if (max_header_bytes != 0 && header_bytes > max_header_bytes) + return format (s, "gre header truncated"); + + indent = format_get_indent (s); + + s = format (s, "GRE %U", format_gre_protocol, p); + + if (max_header_bytes != 0 && header_bytes > max_header_bytes) + { + gre_protocol_info_t * pi = gre_get_protocol_info (gm, p); + vlib_node_t * node = vlib_get_node (gm->vlib_main, pi->node_index); + if (node->format_buffer) + s = format (s, "\n%U%U", + format_white_space, indent, + node->format_buffer, (void *) (h + 1), + max_header_bytes - header_bytes); + } + + return s; +} + +u8 * format_gre_header (u8 * s, va_list * args) +{ + gre_header_t * h = va_arg (*args, gre_header_t *); + return format (s, "%U", format_gre_header_with_length, h, 0); +} + +/* Returns gre protocol as an int in host byte order. */ +uword +unformat_gre_protocol_host_byte_order (unformat_input_t * input, + va_list * args) +{ + u16 * result = va_arg (*args, u16 *); + gre_main_t * gm = &gre_main; + int i; + + /* Named type. */ + if (unformat_user (input, unformat_vlib_number_by_name, + gm->protocol_info_by_name, &i)) + { + gre_protocol_info_t * pi = vec_elt_at_index (gm->protocol_infos, i); + *result = pi->protocol; + return 1; + } + + return 0; +} + +uword +unformat_gre_protocol_net_byte_order (unformat_input_t * input, + va_list * args) +{ + u16 * result = va_arg (*args, u16 *); + if (! unformat_user (input, unformat_gre_protocol_host_byte_order, result)) + return 0; + *result = clib_host_to_net_u16 ((u16) *result); + return 1; +} + +uword +unformat_gre_header (unformat_input_t * input, va_list * args) +{ + u8 ** result = va_arg (*args, u8 **); + gre_header_t _h, * h = &_h; + u16 p; + + if (! unformat (input, "%U", + unformat_gre_protocol_host_byte_order, &p)) + return 0; + + h->protocol = clib_host_to_net_u16 (p); + + /* Add header to result. */ + { + void * p; + u32 n_bytes = sizeof (h[0]); + + vec_add2 (*result, p, n_bytes); + clib_memcpy (p, h, n_bytes); + } + + return 1; +} + +static int +gre_proto_from_vnet_link (vnet_link_t link) +{ + switch (link) + { + case VNET_LINK_IP4: + return (GRE_PROTOCOL_ip4); + case VNET_LINK_IP6: + return (GRE_PROTOCOL_ip6); + case VNET_LINK_MPLS: + return (GRE_PROTOCOL_mpls_unicast); + case VNET_LINK_ETHERNET: + return (GRE_PROTOCOL_teb); + case VNET_LINK_ARP: + return (GRE_PROTOCOL_arp); + } + ASSERT(0); + return (GRE_PROTOCOL_ip4); +} + +static u8* +gre_build_rewrite (vnet_main_t * vnm, + u32 sw_if_index, + vnet_link_t link_type, + const void *dst_address) +{ + gre_main_t * gm = &gre_main; + ip4_and_gre_header_t * h; + u8* rewrite = NULL; + gre_tunnel_t *t; + u32 ti; + + ti = gm->tunnel_index_by_sw_if_index[sw_if_index]; + + if (~0 == ti) + /* not one of ours */ + return (0); + + t = pool_elt_at_index(gm->tunnels, ti); + + vec_validate(rewrite, sizeof(*h)-1); + h = (ip4_and_gre_header_t*)rewrite; + h->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type)); + + h->ip4.ip_version_and_header_length = 0x45; + h->ip4.ttl = 254; + h->ip4.protocol = IP_PROTOCOL_GRE; + /* fixup ip4 header length and checksum after-the-fact */ + h->ip4.src_address.as_u32 = t->tunnel_src.as_u32; + h->ip4.dst_address.as_u32 = t->tunnel_dst.as_u32; + h->ip4.checksum = ip4_header_checksum (&h->ip4); + + return (rewrite); +} + +void +gre_fixup (vlib_main_t *vm, + ip_adjacency_t *adj, + vlib_buffer_t *b0) +{ + ip4_header_t * ip0; + + ip0 = vlib_buffer_get_current (b0); + + /* Fixup the checksum and len fields in the GRE tunnel encap + * that was applied at the midchain node */ + ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + ip0->checksum = ip4_header_checksum (ip0); +} + +void +gre_update_adj (vnet_main_t * vnm, + u32 sw_if_index, + adj_index_t ai) +{ + adj_nbr_midchain_update_rewrite (ai, gre_fixup, + ADJ_MIDCHAIN_FLAG_NONE, + gre_build_rewrite(vnm, sw_if_index, + adj_get_link_type(ai), + NULL)); + + gre_tunnel_stack(ai); +} + +/** + * @brief TX function. Only called L2. L3 traffic uses the adj-midchains + */ +static uword +gre_interface_tx_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + gre_main_t * gm = &gre_main; + u32 next_index; + u32 * from, * to_next, n_left_from, n_left_to_next; + vnet_interface_output_runtime_t * rd = (void *) node->runtime_data; + const gre_tunnel_t *gt = pool_elt_at_index (gm->tunnels, rd->dev_instance); + + /* Vector of buffer / pkt indices we're supposed to process */ + from = vlib_frame_vector_args (frame); + + /* Number of buffers / pkts */ + n_left_from = frame->n_vectors; + + /* Speculatively send the first buffer to the last disposition we used */ + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + /* set up to enqueue to our disposition with index = next_index */ + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + /* + * FIXME DUAL LOOP + */ + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t * b0; + u32 bi0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer(vm, bi0); + + vnet_buffer(b0)->ip.adj_index[VLIB_TX] = gt->l2_adj_index; + + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_tx_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->tunnel_id = gt - gm->tunnels; + tr->length = vlib_buffer_length_in_chain (vm, b0); + tr->src.as_u32 = gt->tunnel_src.as_u32; + tr->dst.as_u32 = gt->tunnel_src.as_u32; + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, gt->l2_tx_arc); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, gre_input_node.index, + GRE_ERROR_PKTS_ENCAP, frame->n_vectors); + + return frame->n_vectors; +} + +static uword +gre_interface_tx (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (gre_interface_tx_inline (vm, node, frame)); +} + +static uword +gre_teb_interface_tx (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (gre_interface_tx_inline (vm, node, frame)); +} + +static u8 * format_gre_tunnel_name (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + return format (s, "gre%d", dev_instance); +} + +static u8 * format_gre_tunnel_teb_name (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + return format (s, "teb-gre%d", dev_instance); +} + +static u8 * format_gre_device (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + CLIB_UNUSED (int verbose) = va_arg (*args, int); + + s = format (s, "GRE tunnel: id %d\n", dev_instance); + return s; +} + +VNET_DEVICE_CLASS (gre_device_class) = { + .name = "GRE tunnel device", + .format_device_name = format_gre_tunnel_name, + .format_device = format_gre_device, + .format_tx_trace = format_gre_tx_trace, + .tx_function = gre_interface_tx, + .admin_up_down_function = gre_interface_admin_up_down, +#ifdef SOON + .clear counter = 0; +#endif +}; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (gre_device_class, + gre_interface_tx) + +VNET_DEVICE_CLASS (gre_device_teb_class) = { + .name = "GRE TEB tunnel device", + .format_device_name = format_gre_tunnel_teb_name, + .format_device = format_gre_device, + .format_tx_trace = format_gre_tx_trace, + .tx_function = gre_teb_interface_tx, + .admin_up_down_function = gre_interface_admin_up_down, +#ifdef SOON + .clear counter = 0; +#endif +}; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (gre_device_teb_class, + gre_teb_interface_tx) + +VNET_HW_INTERFACE_CLASS (gre_hw_interface_class) = { + .name = "GRE", + .format_header = format_gre_header_with_length, + .unformat_header = unformat_gre_header, + .build_rewrite = gre_build_rewrite, + .update_adjacency = gre_update_adj, + .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P, +}; + +static void add_protocol (gre_main_t * gm, + gre_protocol_t protocol, + char * protocol_name) +{ + gre_protocol_info_t * pi; + u32 i; + + vec_add2 (gm->protocol_infos, pi, 1); + i = pi - gm->protocol_infos; + + pi->name = protocol_name; + pi->protocol = protocol; + pi->next_index = pi->node_index = ~0; + + hash_set (gm->protocol_info_by_protocol, protocol, i); + hash_set_mem (gm->protocol_info_by_name, pi->name, i); +} + +static clib_error_t * gre_init (vlib_main_t * vm) +{ + gre_main_t * gm = &gre_main; + clib_error_t * error; + ip_main_t * im = &ip_main; + ip_protocol_info_t * pi; + + memset (gm, 0, sizeof (gm[0])); + gm->vlib_main = vm; + gm->vnet_main = vnet_get_main(); + + if ((error = vlib_call_init_function (vm, ip_main_init))) + return error; + + if ((error = vlib_call_init_function (vm, ip4_lookup_init))) + return error; + + /* Set up the ip packet generator */ + pi = ip_get_protocol_info (im, IP_PROTOCOL_GRE); + pi->format_header = format_gre_header; + pi->unformat_pg_edit = unformat_pg_gre_header; + + gm->protocol_info_by_name = hash_create_string (0, sizeof (uword)); + gm->protocol_info_by_protocol = hash_create (0, sizeof (uword)); + gm->tunnel_by_key = hash_create (0, sizeof (uword)); + +#define _(n,s) add_protocol (gm, GRE_PROTOCOL_##s, #s); + foreach_gre_protocol +#undef _ + + return vlib_call_init_function (vm, gre_input_init); +} + +VLIB_INIT_FUNCTION (gre_init); + +gre_main_t * gre_get_main (vlib_main_t * vm) +{ + vlib_call_init_function (vm, gre_init); + return &gre_main; +} + diff --git a/src/vnet/gre/gre.h b/src/vnet/gre/gre.h new file mode 100644 index 00000000..b6544b9b --- /dev/null +++ b/src/vnet/gre/gre.h @@ -0,0 +1,235 @@ +/* + * gre.h: types/functions for gre. + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef included_gre_h +#define included_gre_h + +#include +#include +#include +#include +#include +#include +#include +#include + +extern vnet_hw_interface_class_t gre_hw_interface_class; + +typedef enum { +#define gre_error(n,s) GRE_ERROR_##n, +#include +#undef gre_error + GRE_N_ERROR, +} gre_error_t; + +/** + * A GRE payload protocol registration + */ +typedef struct { + /** Name (a c string). */ + char * name; + + /** GRE protocol type in host byte order. */ + gre_protocol_t protocol; + + /** Node which handles this type. */ + u32 node_index; + + /** Next index for this type. */ + u32 next_index; +} gre_protocol_info_t; + +/** + * @brief The GRE tunnel type + */ +typedef enum gre_tunnel_tyoe_t_ +{ + /** + * L3 GRE (i.e. this tunnel is in L3 mode) + */ + GRE_TUNNEL_TYPE_L3, + /** + * Transparent Ethernet Bridging - the tunnel is in L2 mode + */ + GRE_TUNNEL_TYPE_TEB, +} gre_tunnel_type_t; + +#define GRE_TUNNEL_TYPE_NAMES { \ + [GRE_TUNNEL_TYPE_L3] = "L3", \ + [GRE_TUNNEL_TYPE_TEB] = "TEB", \ +} + +#define GRE_TUNNEL_N_TYPES ((gre_tunnel_type_t)GRE_TUNNEL_TYPE_TEB+1) + +/** + * @brief A representation of a GRE tunnel + */ +typedef struct { + /** + * Linkage into the FIB object graph + */ + fib_node_t node; + + /** + * The tunnel's source/local address + */ + ip4_address_t tunnel_src; + /** + * The tunnel's destination/remote address + */ + ip4_address_t tunnel_dst; + /** + * The FIB in which the src.dst address are present + */ + u32 outer_fib_index; + u32 hw_if_index; + u32 sw_if_index; + gre_tunnel_type_t type; + + /** + * The FIB entry sourced by the tunnel for its destination prefix + */ + fib_node_index_t fib_entry_index; + + /** + * The tunnel is a child of the FIB entry for its desintion. This is + * so it receives updates when the forwarding information for that entry + * changes. + * The tunnels sibling index on the FIB entry's dependency list. + */ + u32 sibling_index; + + /** + * on a L2 tunnel this is the VLIB arc from the L2-tx to the l2-midchain + */ + u32 l2_tx_arc; + + /** + * an L2 tunnel always rquires an L2 midchain. cache here for DP. + */ + adj_index_t l2_adj_index; +} gre_tunnel_t; + +/** + * @brief GRE related global data + */ +typedef struct { + /** + * pool of tunnel instances + */ + gre_tunnel_t *tunnels; + + /** + * GRE payload protocol registrations + */ + gre_protocol_info_t * protocol_infos; + + /** + * Hash tables mapping name/protocol to protocol info index. + */ + uword * protocol_info_by_name, * protocol_info_by_protocol; + /** + * Hash mapping src/dst addr pair to tunnel + */ + uword * tunnel_by_key; + + /** + * Free vlib hw_if_indices. + * A free list per-tunnel type since the interfaces ctreated are fo different + * types and we cannot change the type. + */ + u32 * free_gre_tunnel_hw_if_indices[GRE_TUNNEL_N_TYPES]; + + /** + * Mapping from sw_if_index to tunnel index + */ + u32 * tunnel_index_by_sw_if_index; + + /* convenience */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} gre_main_t; + +/** + * @brief IPv4 and GRE header. + */ +typedef CLIB_PACKED (struct { + ip4_header_t ip4; + gre_header_t gre; +}) ip4_and_gre_header_t; + +always_inline gre_protocol_info_t * +gre_get_protocol_info (gre_main_t * em, gre_protocol_t protocol) +{ + uword * p = hash_get (em->protocol_info_by_protocol, protocol); + return p ? vec_elt_at_index (em->protocol_infos, p[0]) : 0; +} + +gre_main_t gre_main; + +/* Register given node index to take input for given gre type. */ +void +gre_register_input_type (vlib_main_t * vm, + gre_protocol_t protocol, + u32 node_index); + +extern clib_error_t * gre_interface_admin_up_down (vnet_main_t * vnm, + u32 hw_if_index, + u32 flags); + +extern void gre_tunnel_stack (adj_index_t ai); +extern void gre_update_adj (vnet_main_t * vnm, + u32 sw_if_index, + adj_index_t ai); + +format_function_t format_gre_protocol; +format_function_t format_gre_header; +format_function_t format_gre_header_with_length; + +extern vlib_node_registration_t gre_input_node; +extern vnet_device_class_t gre_device_class; +extern vnet_device_class_t gre_device_teb_class; + +/* Parse gre protocol as 0xXXXX or protocol name. + In either host or network byte order. */ +unformat_function_t unformat_gre_protocol_host_byte_order; +unformat_function_t unformat_gre_protocol_net_byte_order; + +/* Parse gre header. */ +unformat_function_t unformat_gre_header; +unformat_function_t unformat_pg_gre_header; + +void +gre_register_input_protocol (vlib_main_t * vm, + gre_protocol_t protocol, + u32 node_index); + +/* manually added to the interface output node in gre.c */ +#define GRE_OUTPUT_NEXT_LOOKUP 1 + +typedef struct { + u8 is_add; + + ip4_address_t src, dst; + u32 outer_fib_id; + u8 teb; +} vnet_gre_add_del_tunnel_args_t; + +int vnet_gre_add_del_tunnel + (vnet_gre_add_del_tunnel_args_t *a, u32 * sw_if_indexp); + +#endif /* included_gre_h */ diff --git a/src/vnet/gre/gre_api.c b/src/vnet/gre/gre_api.c new file mode 100644 index 00000000..333838c0 --- /dev/null +++ b/src/vnet/gre/gre_api.c @@ -0,0 +1,204 @@ +/* + *------------------------------------------------------------------ + * gre_api.c - gre api + * + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +#include + +#define foreach_vpe_api_msg \ +_(GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel) \ +_(GRE_TUNNEL_DUMP, gre_tunnel_dump) + +static void vl_api_gre_add_del_tunnel_t_handler + (vl_api_gre_add_del_tunnel_t * mp) +{ + vl_api_gre_add_del_tunnel_reply_t *rmp; + int rv = 0; + vnet_gre_add_del_tunnel_args_t _a, *a = &_a; + u32 outer_fib_id; + uword *p; + ip4_main_t *im = &ip4_main; + u32 sw_if_index = ~0; + + p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id)); + if (!p) + { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + outer_fib_id = p[0]; + + /* Check src & dst are different */ + if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) || + (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0)) + { + rv = VNET_API_ERROR_SAME_SRC_DST; + goto out; + } + memset (a, 0, sizeof (*a)); + + a->is_add = mp->is_add; + a->teb = mp->teb; + + /* ip addresses sent in network byte order */ + clib_memcpy (&(a->src), mp->src_address, 4); + clib_memcpy (&(a->dst), mp->dst_address, 4); + + a->outer_fib_id = outer_fib_id; + rv = vnet_gre_add_del_tunnel (a, &sw_if_index); + +out: + /* *INDENT-OFF* */ + REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY, + ({ + rmp->sw_if_index = ntohl (sw_if_index); + })); + /* *INDENT-ON* */ +} + +static void send_gre_tunnel_details + (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) +{ + vl_api_gre_tunnel_details_t *rmp; + ip4_main_t *im = &ip4_main; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS); + clib_memcpy (rmp->src_address, &(t->tunnel_src), 4); + clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4); + rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id); + rmp->teb = (GRE_TUNNEL_TYPE_TEB == t->type); + rmp->sw_if_index = htonl (t->sw_if_index); + rmp->context = context; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void +vl_api_gre_tunnel_dump_t_handler (vl_api_gre_tunnel_dump_t * mp) +{ + unix_shared_memory_queue_t *q; + gre_main_t *gm = &gre_main; + gre_tunnel_t *t; + u32 sw_if_index; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + { + return; + } + + sw_if_index = ntohl (mp->sw_if_index); + + if (~0 == sw_if_index) + { + /* *INDENT-OFF* */ + pool_foreach (t, gm->tunnels, + ({ + send_gre_tunnel_details(t, q, mp->context); + })); + /* *INDENT-ON* */ + } + else + { + if ((sw_if_index >= vec_len (gm->tunnel_index_by_sw_if_index)) || + (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) + { + return; + } + t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]]; + send_gre_tunnel_details (t, q, mp->context); + } +} + +/* + * gre_api_hookup + * Add vpe's API message handlers to the table. + * vlib has alread mapped shared memory and + * added the client registration handlers. + * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() + */ +#define vl_msg_name_crc_list +#include +#undef vl_msg_name_crc_list + +static void +setup_message_id_table (api_main_t * am) +{ +#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); + foreach_vl_msg_name_crc_gre; +#undef _ +} + +static clib_error_t * +gre_api_hookup (vlib_main_t * vm) +{ + api_main_t *am = &api_main; + +#define _(N,n) \ + vl_msg_api_set_handlers(VL_API_##N, #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_vpe_api_msg; +#undef _ + + /* + * Set up the (msg_name, crc, message-id) table + */ + setup_message_id_table (am); + + return 0; +} + +VLIB_API_INIT_FUNCTION (gre_api_hookup); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c new file mode 100644 index 00000000..d624587d --- /dev/null +++ b/src/vnet/gre/interface.c @@ -0,0 +1,606 @@ +/* + * gre_interface.c: gre interfaces + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *gre_tunnel_type_names[] = GRE_TUNNEL_TYPE_NAMES; + +static inline u64 +gre_mk_key (const ip4_address_t *src, + const ip4_address_t *dst, + u32 out_fib_index) +{ + // FIXME. the fib index should be part of the key + return ((u64)src->as_u32 << 32 | (u64)dst->as_u32); +} + +static u8 * +format_gre_tunnel_type (u8 * s, va_list * args) +{ + gre_tunnel_type_t type = va_arg (*args, gre_tunnel_type_t); + + return (format(s, "%s", gre_tunnel_type_names[type])); +} + +static u8 * +format_gre_tunnel (u8 * s, va_list * args) +{ + gre_tunnel_t * t = va_arg (*args, gre_tunnel_t *); + gre_main_t * gm = &gre_main; + + s = format (s, + "[%d] %U (src) %U (dst) payload %U outer_fib_index %d", + t - gm->tunnels, + format_ip4_address, &t->tunnel_src, + format_ip4_address, &t->tunnel_dst, + format_gre_tunnel_type, t->type, + t->outer_fib_index); + + return s; +} + +static gre_tunnel_t * +gre_tunnel_db_find (const ip4_address_t *src, + const ip4_address_t *dst, + u32 out_fib_index) +{ + gre_main_t * gm = &gre_main; + uword * p; + u64 key; + + key = gre_mk_key(src, dst, out_fib_index); + + p = hash_get (gm->tunnel_by_key, key); + + if (NULL == p) + return (NULL); + + return (pool_elt_at_index (gm->tunnels, p[0])); +} + +static void +gre_tunnel_db_add (const gre_tunnel_t *t) +{ + gre_main_t * gm = &gre_main; + u64 key; + + key = gre_mk_key(&t->tunnel_src, &t->tunnel_dst, t->outer_fib_index); + hash_set (gm->tunnel_by_key, key, t - gm->tunnels); +} + +static void +gre_tunnel_db_remove (const gre_tunnel_t *t) +{ + gre_main_t * gm = &gre_main; + u64 key; + + key = gre_mk_key(&t->tunnel_src, &t->tunnel_dst, t->outer_fib_index); + hash_unset (gm->tunnel_by_key, key); +} + +static gre_tunnel_t * +gre_tunnel_from_fib_node (fib_node_t *node) +{ +#if (CLIB_DEBUG > 0) + ASSERT(FIB_NODE_TYPE_GRE_TUNNEL == node->fn_type); +#endif + return ((gre_tunnel_t*) (((char*)node) - + STRUCT_OFFSET_OF(gre_tunnel_t, node))); +} + +/** + * gre_tunnel_stack + * + * 'stack' (resolve the recursion for) the tunnel's midchain adjacency + */ +void +gre_tunnel_stack (adj_index_t ai) +{ + gre_main_t * gm = &gre_main; + ip_adjacency_t *adj; + gre_tunnel_t *gt; + u32 sw_if_index; + + adj = adj_get(ai); + sw_if_index = adj->rewrite_header.sw_if_index; + + if ((vec_len(gm->tunnel_index_by_sw_if_index) < sw_if_index) || + (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) + return; + + gt = pool_elt_at_index(gm->tunnels, + gm->tunnel_index_by_sw_if_index[sw_if_index]); + + /* + * find the adjacency that is contributed by the FIB entry + * that this tunnel resovles via, and use it as the next adj + * in the midchain + */ + if (vnet_hw_interface_get_flags(vnet_get_main(), + gt->hw_if_index) & + VNET_HW_INTERFACE_FLAG_LINK_UP) + { + adj_nbr_midchain_stack( + ai, + fib_entry_contribute_ip_forwarding(gt->fib_entry_index)); + } + else + { + adj_nbr_midchain_unstack(ai); + } +} + +/** + * @brief Call back when restacking all adjacencies on a GRE interface + */ +static adj_walk_rc_t +gre_adj_walk_cb (adj_index_t ai, + void *ctx) +{ + gre_tunnel_stack(ai); + + return (ADJ_WALK_RC_CONTINUE); +} + +static void +gre_tunnel_restack (gre_tunnel_t *gt) +{ + fib_protocol_t proto; + + /* + * walk all the adjacencies on th GRE interface and restack them + */ + FOR_EACH_FIB_IP_PROTOCOL(proto) + { + adj_nbr_walk(gt->sw_if_index, + proto, + gre_adj_walk_cb, + NULL); + } +} + +/** + * Function definition to backwalk a FIB node + */ +static fib_node_back_walk_rc_t +gre_tunnel_back_walk (fib_node_t *node, + fib_node_back_walk_ctx_t *ctx) +{ + gre_tunnel_restack(gre_tunnel_from_fib_node(node)); + + return (FIB_NODE_BACK_WALK_CONTINUE); +} + +/** + * Function definition to get a FIB node from its index + */ +static fib_node_t* +gre_tunnel_fib_node_get (fib_node_index_t index) +{ + gre_tunnel_t * gt; + gre_main_t * gm; + + gm = &gre_main; + gt = pool_elt_at_index(gm->tunnels, index); + + return (>->node); +} + +/** + * Function definition to inform the FIB node that its last lock has gone. + */ +static void +gre_tunnel_last_lock_gone (fib_node_t *node) +{ + /* + * The MPLS GRE tunnel is a root of the graph. As such + * it never has children and thus is never locked. + */ + ASSERT(0); +} + +/* + * Virtual function table registered by MPLS GRE tunnels + * for participation in the FIB object graph. + */ +const static fib_node_vft_t gre_vft = { + .fnv_get = gre_tunnel_fib_node_get, + .fnv_last_lock = gre_tunnel_last_lock_gone, + .fnv_back_walk = gre_tunnel_back_walk, +}; + +static int +vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, + u32 * sw_if_indexp) +{ + gre_main_t * gm = &gre_main; + vnet_main_t * vnm = gm->vnet_main; + ip4_main_t * im = &ip4_main; + gre_tunnel_t * t; + vnet_hw_interface_t * hi; + u32 hw_if_index, sw_if_index; + u32 outer_fib_index; + u8 address[6]; + clib_error_t *error; + + outer_fib_index = ip4_fib_index_from_table_id(a->outer_fib_id); + + if (~0 == outer_fib_index) + return VNET_API_ERROR_NO_SUCH_FIB; + + t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id); + + if (NULL != t) + return VNET_API_ERROR_INVALID_VALUE; + + pool_get_aligned (gm->tunnels, t, CLIB_CACHE_LINE_BYTES); + memset (t, 0, sizeof (*t)); + fib_node_init(&t->node, FIB_NODE_TYPE_GRE_TUNNEL); + + if (a->teb) + t->type = GRE_TUNNEL_TYPE_TEB; + else + t->type = GRE_TUNNEL_TYPE_L3; + + if (vec_len (gm->free_gre_tunnel_hw_if_indices[t->type]) > 0) { + vnet_interface_main_t * im = &vnm->interface_main; + + hw_if_index = gm->free_gre_tunnel_hw_if_indices[t->type] + [vec_len (gm->free_gre_tunnel_hw_if_indices[t->type])-1]; + _vec_len (gm->free_gre_tunnel_hw_if_indices[t->type]) -= 1; + + hi = vnet_get_hw_interface (vnm, hw_if_index); + hi->dev_instance = t - gm->tunnels; + hi->hw_instance = hi->dev_instance; + + /* clear old stats of freed tunnel before reuse */ + sw_if_index = hi->sw_if_index; + vnet_interface_counter_lock(im); + vlib_zero_combined_counter + (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX], sw_if_index); + vlib_zero_combined_counter + (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX], sw_if_index); + vlib_zero_simple_counter + (&im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP], sw_if_index); + vnet_interface_counter_unlock(im); + if (GRE_TUNNEL_TYPE_TEB == t->type) + { + t->l2_tx_arc = vlib_node_add_named_next(vlib_get_main(), + hi->tx_node_index, + "adj-l2-midchain"); + } + } else { + if (GRE_TUNNEL_TYPE_TEB == t->type) + { + /* Default MAC address (d00b:eed0:0000 + sw_if_index) */ + memset (address, 0, sizeof (address)); + address[0] = 0xd0; + address[1] = 0x0b; + address[2] = 0xee; + address[3] = 0xd0; + address[4] = t - gm->tunnels; + + error = ethernet_register_interface(vnm, + gre_device_teb_class.index, + t - gm->tunnels, address, + &hw_if_index, + 0); + + if (error) + { + clib_error_report (error); + return VNET_API_ERROR_INVALID_REGISTRATION; + } + hi = vnet_get_hw_interface (vnm, hw_if_index); + + t->l2_tx_arc = vlib_node_add_named_next(vlib_get_main(), + hi->tx_node_index, + "adj-l2-midchain"); + } else { + hw_if_index = vnet_register_interface(vnm, + gre_device_class.index, + t - gm->tunnels, + gre_hw_interface_class.index, + t - gm->tunnels); + } + hi = vnet_get_hw_interface (vnm, hw_if_index); + sw_if_index = hi->sw_if_index; + } + + t->hw_if_index = hw_if_index; + t->outer_fib_index = outer_fib_index; + t->sw_if_index = sw_if_index; + t->l2_adj_index = ADJ_INDEX_INVALID; + + vec_validate_init_empty (gm->tunnel_index_by_sw_if_index, sw_if_index, ~0); + gm->tunnel_index_by_sw_if_index[sw_if_index] = t - gm->tunnels; + + vec_validate (im->fib_index_by_sw_if_index, sw_if_index); + + hi->min_packet_bytes = 64 + sizeof (gre_header_t) + sizeof (ip4_header_t); + hi->per_packet_overhead_bytes = + /* preamble */ 8 + /* inter frame gap */ 12; + + /* Standard default gre MTU. */ + hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000; + + clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); + clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); + + gre_tunnel_db_add(t); + + /* + * source the FIB entry for the tunnel's destination + * and become a child thereof. The tunnel will then get poked + * when the forwarding for the entry updates, and the tunnel can + * re-stack accordingly + */ + const fib_prefix_t tun_dst_pfx = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + .ip4 = t->tunnel_dst, + } + }; + + t->fib_entry_index = + fib_table_entry_special_add(outer_fib_index, + &tun_dst_pfx, + FIB_SOURCE_RR, + FIB_ENTRY_FLAG_NONE, + ADJ_INDEX_INVALID); + t->sibling_index = + fib_entry_child_add(t->fib_entry_index, + FIB_NODE_TYPE_GRE_TUNNEL, + t - gm->tunnels); + + clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); + clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); + + if (GRE_TUNNEL_TYPE_TEB == t->type) + { + t->l2_adj_index = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + VNET_LINK_ETHERNET, + &zero_addr, + sw_if_index); + gre_update_adj(vnm, t->sw_if_index, t->l2_adj_index); + } + + if (sw_if_indexp) + *sw_if_indexp = sw_if_index; + + return 0; +} + +static int +vnet_gre_tunnel_delete (vnet_gre_add_del_tunnel_args_t *a, + u32 * sw_if_indexp) +{ + gre_main_t * gm = &gre_main; + vnet_main_t * vnm = gm->vnet_main; + gre_tunnel_t * t; + u32 sw_if_index; + + t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id); + + if (NULL == t) + return VNET_API_ERROR_NO_SUCH_ENTRY; + + sw_if_index = t->sw_if_index; + vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */); + /* make sure tunnel is removed from l2 bd or xconnect */ + set_int_l2_mode(gm->vlib_main, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0); + vec_add1 (gm->free_gre_tunnel_hw_if_indices[t->type], t->hw_if_index); + gm->tunnel_index_by_sw_if_index[sw_if_index] = ~0; + + if (GRE_TUNNEL_TYPE_TEB == t->type) + adj_unlock(t->l2_adj_index); + + if (t->l2_adj_index != ADJ_INDEX_INVALID) + adj_unlock(t->l2_adj_index); + + fib_entry_child_remove(t->fib_entry_index, + t->sibling_index); + fib_table_entry_delete_index(t->fib_entry_index, + FIB_SOURCE_RR); + + gre_tunnel_db_remove(t); + fib_node_deinit(&t->node); + pool_put (gm->tunnels, t); + + if (sw_if_indexp) + *sw_if_indexp = sw_if_index; + + return 0; +} + +int +vnet_gre_add_del_tunnel (vnet_gre_add_del_tunnel_args_t *a, + u32 * sw_if_indexp) +{ + if (a->is_add) + return (vnet_gre_tunnel_add(a, sw_if_indexp)); + else + return (vnet_gre_tunnel_delete(a, sw_if_indexp)); +} + +clib_error_t * +gre_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) +{ + gre_main_t * gm = &gre_main; + vnet_hw_interface_t * hi; + gre_tunnel_t *t; + u32 ti; + + hi = vnet_get_hw_interface (vnm, hw_if_index); + + if (NULL == gm->tunnel_index_by_sw_if_index || + hi->sw_if_index >= vec_len(gm->tunnel_index_by_sw_if_index)) + return (NULL); + + ti = gm->tunnel_index_by_sw_if_index[hi->sw_if_index]; + + if (~0 == ti) + /* not one of ours */ + return (NULL); + + t = pool_elt_at_index(gm->tunnels, ti); + + if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) + vnet_hw_interface_set_flags (vnm, hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); + else + vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */); + + gre_tunnel_restack(t); + + return /* no error */ 0; +} + +static clib_error_t * +create_gre_tunnel_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, * line_input = &_line_input; + vnet_gre_add_del_tunnel_args_t _a, * a = &_a; + ip4_address_t src, dst; + u32 outer_fib_id = 0; + u8 teb = 0; + int rv; + u32 num_m_args = 0; + u8 is_add = 1; + u32 sw_if_index; + + /* Get a line of input. */ + if (! unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "src %U", unformat_ip4_address, &src)) + num_m_args++; + else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst)) + num_m_args++; + else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id)) + ; + else if (unformat (line_input, "teb")) + teb = 1; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + unformat_free (line_input); + + if (num_m_args < 2) + return clib_error_return (0, "mandatory argument(s) missing"); + + if (memcmp (&src, &dst, sizeof(src)) == 0) + return clib_error_return (0, "src and dst are identical"); + + memset (a, 0, sizeof (*a)); + a->outer_fib_id = outer_fib_id; + a->teb = teb; + clib_memcpy(&a->src, &src, sizeof(src)); + clib_memcpy(&a->dst, &dst, sizeof(dst)); + + if (is_add) + rv = vnet_gre_tunnel_add(a, &sw_if_index); + else + rv = vnet_gre_tunnel_delete(a, &sw_if_index); + + switch(rv) + { + case 0: + vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index); + break; + case VNET_API_ERROR_INVALID_VALUE: + return clib_error_return (0, "GRE tunnel already exists..."); + case VNET_API_ERROR_NO_SUCH_FIB: + return clib_error_return (0, "outer fib ID %d doesn't exist\n", + outer_fib_id); + default: + return clib_error_return (0, "vnet_gre_add_del_tunnel returned %d", rv); + } + + return 0; +} + +VLIB_CLI_COMMAND (create_gre_tunnel_command, static) = { + .path = "create gre tunnel", + .short_help = "create gre tunnel src dst " + "[outer-fib-id ] [teb] [del]", + .function = create_gre_tunnel_command_fn, +}; + +static clib_error_t * +show_gre_tunnel_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + gre_main_t * gm = &gre_main; + gre_tunnel_t * t; + u32 ti = ~0; + + if (pool_elts (gm->tunnels) == 0) + vlib_cli_output (vm, "No GRE tunnels configured..."); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%d", &ti)) + ; + else + break; + } + + if (~0 == ti) + { + pool_foreach (t, gm->tunnels, + ({ + vlib_cli_output (vm, "%U", format_gre_tunnel, t); + })); + } + else + { + t = pool_elt_at_index(gm->tunnels, ti); + + vlib_cli_output (vm, "%U", format_gre_tunnel, t); + } + + return 0; +} + +VLIB_CLI_COMMAND (show_gre_tunnel_command, static) = { + .path = "show gre tunnel", + .function = show_gre_tunnel_command_fn, +}; + +/* force inclusion from application's main.c */ +clib_error_t *gre_interface_init (vlib_main_t *vm) +{ + fib_node_register_type(FIB_NODE_TYPE_GRE_TUNNEL, &gre_vft); + + return 0; +} +VLIB_INIT_FUNCTION(gre_interface_init); diff --git a/src/vnet/gre/node.c b/src/vnet/gre/node.c new file mode 100644 index 00000000..86f7a6ee --- /dev/null +++ b/src/vnet/gre/node.c @@ -0,0 +1,531 @@ +/* + * node.c: gre packet processing + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#define foreach_gre_input_next \ +_(PUNT, "error-punt") \ +_(DROP, "error-drop") \ +_(ETHERNET_INPUT, "ethernet-input") \ +_(IP4_INPUT, "ip4-input") \ +_(IP6_INPUT, "ip6-input") \ +_(MPLS_INPUT, "mpls-input") + +typedef enum { +#define _(s,n) GRE_INPUT_NEXT_##s, + foreach_gre_input_next +#undef _ + GRE_INPUT_N_NEXT, +} gre_input_next_t; + +typedef struct { + u32 tunnel_id; + u32 length; + ip4_address_t src; + ip4_address_t dst; +} gre_rx_trace_t; + +u8 * format_gre_rx_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + gre_rx_trace_t * t = va_arg (*args, gre_rx_trace_t *); + + s = format (s, "GRE: tunnel %d len %d src %U dst %U", + t->tunnel_id, clib_net_to_host_u16(t->length), + format_ip4_address, &t->src.as_u8, + format_ip4_address, &t->dst.as_u8); + return s; +} + +typedef struct { + /* Sparse vector mapping gre protocol in network byte order + to next index. */ + u16 * next_by_protocol; +} gre_input_runtime_t; + +static uword +gre_input (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + gre_main_t * gm = &gre_main; + gre_input_runtime_t * rt = (void *) node->runtime_data; + __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next; + u64 cached_tunnel_key = (u64) ~0; + u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0; + + u32 cpu_index = os_get_cpu_number(); + u32 len; + vnet_interface_main_t *im = &gm->vnet_main->interface_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, + to_next, n_left_to_next); + + while (n_left_from >= 4 && n_left_to_next >= 2) + { + u32 bi0, bi1; + vlib_buffer_t * b0, * b1; + gre_header_t * h0, * h1; + u16 version0, version1; + int verr0, verr1; + u32 i0, i1, next0, next1, protocol0, protocol1; + ip4_header_t *ip0, *ip1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t * p2, * p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); + + CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD); + CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD); + } + + bi0 = from[0]; + bi1 = from[1]; + to_next[0] = bi0; + to_next[1] = bi1; + from += 2; + to_next += 2; + n_left_to_next -= 2; + n_left_from -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + /* ip4_local hands us the ip header, not the gre header */ + ip0 = vlib_buffer_get_current (b0); + ip1 = vlib_buffer_get_current (b1); + + /* Save src + dst ip4 address, e.g. for mpls-o-gre */ + vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; + vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; + vnet_buffer(b1)->gre.src = ip1->src_address.as_u32; + vnet_buffer(b1)->gre.dst = ip1->dst_address.as_u32; + + vlib_buffer_advance (b0, sizeof (*ip0)); + vlib_buffer_advance (b1, sizeof (*ip1)); + + h0 = vlib_buffer_get_current (b0); + h1 = vlib_buffer_get_current (b1); + + /* Index sparse array with network byte order. */ + protocol0 = h0->protocol; + protocol1 = h1->protocol; + sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1, + &i0, &i1); + next0 = vec_elt(rt->next_by_protocol, i0); + next1 = vec_elt(rt->next_by_protocol, i1); + + b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; + b1->error = node->errors[i1 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; + + version0 = clib_net_to_host_u16 (h0->flags_and_version); + verr0 = version0 & GRE_VERSION_MASK; + version1 = clib_net_to_host_u16 (h1->flags_and_version); + verr1 = version1 & GRE_VERSION_MASK; + + b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] + : b0->error; + next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0; + b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] + : b1->error; + next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1; + + + /* RPF check for ip4/ip6 input */ + if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_IP4_INPUT + || next0 == GRE_INPUT_NEXT_IP6_INPUT + || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT + || next0 == GRE_INPUT_NEXT_MPLS_INPUT)) + { + u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | + (u64)(vnet_buffer(b0)->gre.src); + + if (cached_tunnel_key != key) + { + vnet_hw_interface_t * hi; + gre_tunnel_t * t; + uword * p; + + p = hash_get (gm->tunnel_by_key, key); + if (!p) + { + next0 = GRE_INPUT_NEXT_DROP; + b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; + goto drop0; + } + t = pool_elt_at_index (gm->tunnels, p[0]); + hi = vnet_get_hw_interface (gm->vnet_main, + t->hw_if_index); + tunnel_sw_if_index = hi->sw_if_index; + + cached_tunnel_sw_if_index = tunnel_sw_if_index; + } + else + { + tunnel_sw_if_index = cached_tunnel_sw_if_index; + } + } + else + { + next0 = GRE_INPUT_NEXT_DROP; + goto drop0; + } + len = vlib_buffer_length_in_chain (vm, b0); + vlib_increment_combined_counter (im->combined_sw_if_counters + + VNET_INTERFACE_COUNTER_RX, + cpu_index, + tunnel_sw_if_index, + 1 /* packets */, + len /* bytes */); + + vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; + +drop0: + if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_IP4_INPUT + || next1 == GRE_INPUT_NEXT_IP6_INPUT + || next1 == GRE_INPUT_NEXT_ETHERNET_INPUT + || next1 == GRE_INPUT_NEXT_MPLS_INPUT)) + { + u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) | + (u64)(vnet_buffer(b1)->gre.src); + + if (cached_tunnel_key != key) + { + vnet_hw_interface_t * hi; + gre_tunnel_t * t; + uword * p; + + p = hash_get (gm->tunnel_by_key, key); + if (!p) + { + next1 = GRE_INPUT_NEXT_DROP; + b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; + goto drop1; + } + t = pool_elt_at_index (gm->tunnels, p[0]); + hi = vnet_get_hw_interface (gm->vnet_main, + t->hw_if_index); + tunnel_sw_if_index = hi->sw_if_index; + + cached_tunnel_sw_if_index = tunnel_sw_if_index; + } + else + { + tunnel_sw_if_index = cached_tunnel_sw_if_index; + } + } + else + { + next1 = GRE_INPUT_NEXT_DROP; + goto drop1; + } + len = vlib_buffer_length_in_chain (vm, b1); + vlib_increment_combined_counter (im->combined_sw_if_counters + + VNET_INTERFACE_COUNTER_RX, + cpu_index, + tunnel_sw_if_index, + 1 /* packets */, + len /* bytes */); + + vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; + +drop1: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_rx_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->tunnel_id = tunnel_sw_if_index; + tr->length = ip0->length; + tr->src.as_u32 = ip0->src_address.as_u32; + tr->dst.as_u32 = ip0->dst_address.as_u32; + } + + if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_rx_trace_t *tr = vlib_add_trace (vm, node, + b1, sizeof (*tr)); + tr->tunnel_id = tunnel_sw_if_index; + tr->length = ip1->length; + tr->src.as_u32 = ip1->src_address.as_u32; + tr->dst.as_u32 = ip1->dst_address.as_u32; + } + + vlib_buffer_advance (b0, sizeof (*h0)); + vlib_buffer_advance (b1, sizeof (*h1)); + + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, + to_next, n_left_to_next, + bi0, bi1, next0, next1); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t * b0; + gre_header_t * h0; + ip4_header_t * ip0; + u16 version0; + int verr0; + u32 i0, next0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + ip0 = vlib_buffer_get_current (b0); + + vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; + vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; + + vlib_buffer_advance (b0, sizeof (*ip0)); + + h0 = vlib_buffer_get_current (b0); + + i0 = sparse_vec_index (rt->next_by_protocol, h0->protocol); + next0 = vec_elt(rt->next_by_protocol, i0); + + b0->error = + node->errors[i0 == SPARSE_VEC_INVALID_INDEX + ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; + + version0 = clib_net_to_host_u16 (h0->flags_and_version); + verr0 = version0 & GRE_VERSION_MASK; + b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] + : b0->error; + next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0; + + + /* For IP payload we need to find source interface + so we can increase counters and help forward node to + pick right FIB */ + /* RPF check for ip4/ip6 input */ + if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_IP4_INPUT + || next0 == GRE_INPUT_NEXT_IP6_INPUT + || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT + || next0 == GRE_INPUT_NEXT_MPLS_INPUT)) + { + u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | + (u64)(vnet_buffer(b0)->gre.src); + + if (cached_tunnel_key != key) + { + vnet_hw_interface_t * hi; + gre_tunnel_t * t; + uword * p; + + p = hash_get (gm->tunnel_by_key, key); + if (!p) + { + next0 = GRE_INPUT_NEXT_DROP; + b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; + goto drop; + } + t = pool_elt_at_index (gm->tunnels, p[0]); + hi = vnet_get_hw_interface (gm->vnet_main, + t->hw_if_index); + tunnel_sw_if_index = hi->sw_if_index; + + cached_tunnel_sw_if_index = tunnel_sw_if_index; + } + else + { + tunnel_sw_if_index = cached_tunnel_sw_if_index; + } + } + else + { + next0 = GRE_INPUT_NEXT_DROP; + goto drop; + } + len = vlib_buffer_length_in_chain (vm, b0); + vlib_increment_combined_counter (im->combined_sw_if_counters + + VNET_INTERFACE_COUNTER_RX, + cpu_index, + tunnel_sw_if_index, + 1 /* packets */, + len /* bytes */); + + vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; + +drop: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_rx_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->tunnel_id = tunnel_sw_if_index; + tr->length = ip0->length; + tr->src.as_u32 = ip0->src_address.as_u32; + tr->dst.as_u32 = ip0->dst_address.as_u32; + } + + vlib_buffer_advance (b0, sizeof (*h0)); + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, gre_input_node.index, + GRE_ERROR_PKTS_DECAP, from_frame->n_vectors); + return from_frame->n_vectors; +} + +static char * gre_error_strings[] = { +#define gre_error(n,s) s, +#include "error.def" +#undef gre_error +}; + +VLIB_REGISTER_NODE (gre_input_node) = { + .function = gre_input, + .name = "gre-input", + /* Takes a vector of packets. */ + .vector_size = sizeof (u32), + + .runtime_data_bytes = sizeof (gre_input_runtime_t), + + .n_errors = GRE_N_ERROR, + .error_strings = gre_error_strings, + + .n_next_nodes = GRE_INPUT_N_NEXT, + .next_nodes = { +#define _(s,n) [GRE_INPUT_NEXT_##s] = n, + foreach_gre_input_next +#undef _ + }, + + .format_buffer = format_gre_header_with_length, + .format_trace = format_gre_rx_trace, + .unformat_buffer = unformat_gre_header, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (gre_input_node, gre_input) + +void +gre_register_input_protocol (vlib_main_t * vm, + gre_protocol_t protocol, + u32 node_index) +{ + gre_main_t * em = &gre_main; + gre_protocol_info_t * pi; + gre_input_runtime_t * rt; + u16 * n; + + { + clib_error_t * error = vlib_call_init_function (vm, gre_input_init); + if (error) + clib_error_report (error); + } + + pi = gre_get_protocol_info (em, protocol); + pi->node_index = node_index; + pi->next_index = vlib_node_add_next (vm, + gre_input_node.index, + node_index); + + /* Setup gre protocol -> next index sparse vector mapping. */ + rt = vlib_node_get_runtime_data (vm, gre_input_node.index); + n = sparse_vec_validate (rt->next_by_protocol, + clib_host_to_net_u16 (protocol)); + n[0] = pi->next_index; +} + +static void +gre_setup_node (vlib_main_t * vm, u32 node_index) +{ + vlib_node_t * n = vlib_get_node (vm, node_index); + pg_node_t * pn = pg_get_node (node_index); + + n->format_buffer = format_gre_header_with_length; + n->unformat_buffer = unformat_gre_header; + pn->unformat_edit = unformat_pg_gre_header; +} + +static clib_error_t * gre_input_init (vlib_main_t * vm) +{ + gre_input_runtime_t * rt; + vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input; + + { + clib_error_t * error; + error = vlib_call_init_function (vm, gre_init); + if (error) + clib_error_report (error); + } + + gre_setup_node (vm, gre_input_node.index); + + rt = vlib_node_get_runtime_data (vm, gre_input_node.index); + + rt->next_by_protocol = sparse_vec_new + (/* elt bytes */ sizeof (rt->next_by_protocol[0]), + /* bits in index */ BITS (((gre_header_t *) 0)->protocol)); + + /* These could be moved to the supported protocol input node defn's */ + ethernet_input = vlib_get_node_by_name (vm, (u8 *)"ethernet-input"); + ASSERT(ethernet_input); + ip4_input = vlib_get_node_by_name (vm, (u8 *)"ip4-input"); + ASSERT(ip4_input); + ip6_input = vlib_get_node_by_name (vm, (u8 *)"ip6-input"); + ASSERT(ip6_input); + mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-input"); + ASSERT(mpls_unicast_input); + + gre_register_input_protocol (vm, GRE_PROTOCOL_teb, + ethernet_input->index); + + gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, + ip4_input->index); + + gre_register_input_protocol (vm, GRE_PROTOCOL_ip6, + ip6_input->index); + + gre_register_input_protocol (vm, GRE_PROTOCOL_mpls_unicast, + mpls_unicast_input->index); + + ip4_register_protocol (IP_PROTOCOL_GRE, gre_input_node.index); + + return 0; +} + +VLIB_INIT_FUNCTION (gre_input_init); diff --git a/src/vnet/gre/packet.h b/src/vnet/gre/packet.h new file mode 100644 index 00000000..cc2ccda9 --- /dev/null +++ b/src/vnet/gre/packet.h @@ -0,0 +1,55 @@ +#ifndef included_vnet_gre_packet_h +#define included_vnet_gre_packet_h + +/* + * GRE packet format + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define foreach_gre_protocol \ +_ (0x0800, ip4) \ +_ (0x86DD, ip6) \ +_ (0x6558, teb) \ +_ (0x0806, arp) \ +_ (0x8847, mpls_unicast) \ +_ (0x894F, nsh) + +typedef enum { +#define _(n,f) GRE_PROTOCOL_##f = n, + foreach_gre_protocol +#undef _ +} gre_protocol_t; + +typedef struct { + /* flags and version */ + u16 flags_and_version; + /* unimplemented at the moment */ +#define GRE_FLAGS_CHECKSUM (1 << 15) + + /* deprecated, according to rfc2784 */ +#define GRE_FLAGS_ROUTING (1 << 14) +#define GRE_FLAGS_KEY (1 << 13) +#define GRE_FLAGS_SEQUENCE (1 << 12) +#define GRE_FLAGS_STRICT_SOURCE_ROUTE (1 << 11) + + /* version 1 is PPTP which we don't support */ +#define GRE_SUPPORTED_VERSION 0 +#define GRE_VERSION_MASK 0x7 + + /* 0x800 for ip4, etc. */ + u16 protocol; +} gre_header_t; + +#endif /* included_vnet_gre_packet_h */ diff --git a/src/vnet/gre/pg.c b/src/vnet/gre/pg.c new file mode 100644 index 00000000..cc065d3b --- /dev/null +++ b/src/vnet/gre/pg.c @@ -0,0 +1,77 @@ +/* + * hdlc_pg.c: packet generator gre interface + * + * Copyright (c) 2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +typedef struct { + pg_edit_t flags_and_version; + pg_edit_t protocol; +} pg_gre_header_t; + +static inline void +pg_gre_header_init (pg_gre_header_t * e) +{ + pg_edit_init (&e->flags_and_version, gre_header_t, flags_and_version); + pg_edit_init (&e->protocol, gre_header_t, protocol); +} + +uword +unformat_pg_gre_header (unformat_input_t * input, va_list * args) +{ + pg_stream_t * s = va_arg (*args, pg_stream_t *); + pg_gre_header_t * h; + u32 group_index, error; + + h = pg_create_edit_group (s, sizeof (h[0]), sizeof (gre_header_t), + &group_index); + pg_gre_header_init (h); + + pg_edit_set_fixed (&h->flags_and_version, 0); + + error = 1; + if (! unformat (input, "%U", + unformat_pg_edit, + unformat_gre_protocol_net_byte_order, &h->protocol)) + goto done; + + { + gre_main_t * pm = &gre_main; + gre_protocol_info_t * pi = 0; + pg_node_t * pg_node = 0; + + if (h->protocol.type == PG_EDIT_FIXED) + { + u16 t = *(u16 *) h->protocol.values[PG_EDIT_LO]; + pi = gre_get_protocol_info (pm, clib_net_to_host_u16 (t)); + if (pi && pi->node_index != ~0) + pg_node = pg_get_node (pi->node_index); + } + + if (pg_node && pg_node->unformat_edit + && unformat_user (input, pg_node->unformat_edit, s)) + ; + } + + error = 0; + done: + if (error) + pg_free_edit_group (s); + return error == 0; +} + -- cgit 1.2.3-korg From ce1b4c7f05ce28d7b73eb7ed0a8ea4bd483f09e9 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 26 Jan 2017 14:25:34 -0800 Subject: Basic support for LISP-GPE encapsulated NSH packets Change-Id: I97fedb0f70dd18ed9bbe985407cc5fe714e8a2e2 Signed-off-by: Florin Coras --- src/vnet.am | 2 + src/vnet/adj/adj_internal.h | 4 +- src/vnet/adj/adj_midchain.c | 20 +++ src/vnet/adj/adj_nsh.c | 211 ++++++++++++++++++++++ src/vnet/adj/adj_nsh.h | 31 ++++ src/vnet/dpo/dpo.c | 2 + src/vnet/dpo/dpo.h | 6 +- src/vnet/fib/fib_entry_delegate.c | 4 + src/vnet/fib/fib_entry_delegate.h | 3 +- src/vnet/fib/fib_entry_src.c | 1 + src/vnet/fib/fib_path.c | 4 + src/vnet/fib/fib_types.c | 6 + src/vnet/fib/fib_types.h | 11 +- src/vnet/gre/gre.c | 3 + src/vnet/interface.c | 1 + src/vnet/interface.h | 4 +- src/vnet/lisp-cp/control.c | 32 ++++ src/vnet/lisp-cp/lisp_api.c | 2 + src/vnet/lisp-cp/lisp_cp_dpo.c | 5 + src/vnet/lisp-cp/lisp_types.c | 43 ++++- src/vnet/lisp-cp/lisp_types.h | 15 +- src/vnet/lisp-gpe/interface.c | 196 ++++++++++++++++++++- src/vnet/lisp-gpe/lisp_gpe.c | 2 +- src/vnet/lisp-gpe/lisp_gpe.h | 9 + src/vnet/lisp-gpe/lisp_gpe_adjacency.c | 8 +- src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c | 309 ++++++++++++++++++++++++++++++++- src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h | 31 +++- src/vnet/mfib/mfib_entry.c | 1 + 28 files changed, 944 insertions(+), 22 deletions(-) create mode 100644 src/vnet/adj/adj_nsh.c create mode 100644 src/vnet/adj/adj_nsh.h (limited to 'src/vnet/gre') diff --git a/src/vnet.am b/src/vnet.am index 9b148f69..a8cc696f 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -958,12 +958,14 @@ libvnet_la_SOURCES += \ vnet/adj/adj_midchain.c \ vnet/adj/adj_mcast.c \ vnet/adj/adj_l2.c \ + vnet/adj/adj_nsh.c \ vnet/adj/adj.c nobase_include_HEADERS += \ vnet/adj/adj.h \ vnet/adj/adj_types.h \ vnet/adj/adj_glean.h \ + vnet/adj/adj_nsh.h \ vnet/adj/adj_nbr.h ######################################## diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h index ece59121..30668625 100644 --- a/src/vnet/adj/adj_internal.h +++ b/src/vnet/adj/adj_internal.h @@ -20,7 +20,7 @@ #include #include #include - +#include /** * big switch to turn on Adjacency debugging @@ -53,6 +53,8 @@ adj_get_rewrite_node (vnet_link_t linkt) return (mpls_output_node.index); case VNET_LINK_ETHERNET: return (adj_l2_rewrite_node.index); + case VNET_LINK_NSH: + return (adj_nsh_rewrite_node.index); case VNET_LINK_ARP: break; } diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c index 8c6ab5aa..35cdb003 100644 --- a/src/vnet/adj/adj_midchain.c +++ b/src/vnet/adj/adj_midchain.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -308,6 +309,18 @@ VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = { .runs_before = VNET_FEATURES ("error-drop"), .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET], }; +VNET_FEATURE_INIT (adj_midchain_tx_nsh, static) = { + .arc_name = "nsh-output", + .node_name = "adj-midchain-tx", + .runs_before = VNET_FEATURES ("error-drop"), + .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_NSH], +}; +VNET_FEATURE_INIT (adj_midchain_tx_no_count_nsh, static) = { + .arc_name = "nsh-output", + .node_name = "adj-midchain-tx-no-count", + .runs_before = VNET_FEATURES ("error-drop"), + .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_NSH], +}; static inline u32 adj_get_midchain_node (vnet_link_t link) @@ -321,6 +334,8 @@ adj_get_midchain_node (vnet_link_t link) return (mpls_midchain_node.index); case VNET_LINK_ETHERNET: return (adj_l2_midchain_node.index); + case VNET_LINK_NSH: + return (adj_nsh_midchain_node.index); case VNET_LINK_ARP: break; } @@ -354,6 +369,11 @@ adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj) arc = ethernet_main.output_feature_arc_index; break; } + case VNET_LINK_NSH: + { + arc = nsh_main_dummy.output_feature_arc_index; + break; + } case VNET_LINK_ARP: ASSERT(0); break; diff --git a/src/vnet/adj/adj_nsh.c b/src/vnet/adj/adj_nsh.c new file mode 100644 index 00000000..9a0f9d8b --- /dev/null +++ b/src/vnet/adj/adj_nsh.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +nsh_main_dummy_t nsh_main_dummy; + +/** + * @brief Trace data for a NSH Midchain + */ +typedef struct adj_nsh_trace_t_ { + /** Adjacency index taken. */ + u32 adj_index; +} adj_nsh_trace_t; + +static u8 * +format_adj_nsh_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + adj_nsh_trace_t * t = va_arg (*args, adj_nsh_trace_t *); + + s = format (s, "adj-idx %d : %U", + t->adj_index, + format_ip_adjacency, t->adj_index, FORMAT_IP_ADJACENCY_NONE); + return s; +} + +typedef enum adj_nsh_rewrite_next_t_ +{ + ADJ_NSH_REWRITE_NEXT_DROP, +} adj_gpe_rewrite_next_t; + +always_inline uword +adj_nsh_rewrite_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, + int is_midchain) +{ + u32 * from = vlib_frame_vector_args (frame); + u32 n_left_from, n_left_to_next, * to_next, next_index; + u32 cpu_index = os_get_cpu_number(); + + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + ip_adjacency_t * adj0; + vlib_buffer_t * p0; + char *h0; + u32 pi0, rw_len0, adj_index0, next0 = 0; + u32 tx_sw_if_index0; + + pi0 = to_next[0] = from[0]; + from += 1; + n_left_from -= 1; + to_next += 1; + n_left_to_next -= 1; + + p0 = vlib_get_buffer (vm, pi0); + h0 = vlib_buffer_get_current (p0); + + adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + + /* We should never rewrite a pkt using the MISS adjacency */ + ASSERT(adj_index0); + + adj0 = adj_get (adj_index0); + + /* Guess we are only writing on simple IP4 header. */ + vnet_rewrite_one_header(adj0[0], h0, sizeof(ip4_header_t)); + + /* Update packet buffer attributes/set output interface. */ + rw_len0 = adj0[0].rewrite_header.data_bytes; + vnet_buffer(p0)->ip.save_rewrite_length = rw_len0; + + vlib_increment_combined_counter(&adjacency_counters, + cpu_index, + adj_index0, + /* packet increment */ 0, + /* byte increment */ rw_len0); + + /* Check MTU of outgoing interface. */ + if (PREDICT_TRUE((vlib_buffer_length_in_chain (vm, p0) <= + adj0[0].rewrite_header.max_l3_packet_bytes))) + { + /* Don't adjust the buffer for ttl issue; icmp-error node wants + * to see the IP headerr */ + p0->current_data -= rw_len0; + p0->current_length += rw_len0; + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; + + if (is_midchain) + { + adj0->sub_type.midchain.fixup_func(vm, adj0, p0); + } + + vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; + + /* + * Follow the feature ARC. this will result eventually in + * the midchain-tx node + */ + vnet_feature_arc_start (nsh_main_dummy.output_feature_arc_index, + tx_sw_if_index0, &next0, p0); + } + else + { + /* can't fragment NSH */ + next0 = ADJ_NSH_REWRITE_NEXT_DROP; + } + + if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) + { + adj_nsh_trace_t *tr = vlib_add_trace (vm, node, + p0, sizeof (*tr)); + tr->adj_index = vnet_buffer(p0)->ip.adj_index[VLIB_TX]; + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + pi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return frame->n_vectors; +} + +static uword +adj_nsh_rewrite (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return adj_nsh_rewrite_inline (vm, node, frame, 0); +} + +static uword +adj_nsh_midchain (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return adj_nsh_rewrite_inline (vm, node, frame, 1); +} + +VLIB_REGISTER_NODE (adj_nsh_rewrite_node) = { + .function = adj_nsh_rewrite, + .name = "adj-nsh-rewrite", + .vector_size = sizeof (u32), + + .format_trace = format_adj_nsh_trace, + + .n_next_nodes = 1, + .next_nodes = { + [ADJ_NSH_REWRITE_NEXT_DROP] = "error-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (adj_nsh_rewrite_node, adj_nsh_rewrite) + +VLIB_REGISTER_NODE (adj_nsh_midchain_node) = { + .function = adj_nsh_midchain, + .name = "adj-nsh-midchain", + .vector_size = sizeof (u32), + + .format_trace = format_adj_nsh_trace, + + .n_next_nodes = 1, + .next_nodes = { + [ADJ_NSH_REWRITE_NEXT_DROP] = "error-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (adj_nsh_midchain_node, adj_nsh_midchain) + +/* Built-in ip4 tx feature path definition */ +/* *INDENT-OFF* */ +VNET_FEATURE_ARC_INIT (nsh_output, static) = +{ + .arc_name = "nsh-output", + .start_nodes = VNET_FEATURES ("adj-nsh-midchain"), + .arc_index_ptr = &nsh_main_dummy.output_feature_arc_index, +}; + +VNET_FEATURE_INIT (nsh_tx_drop, static) = +{ + .arc_name = "nsh-output", + .node_name = "error-drop", + .runs_before = 0, /* not before any other features */ +}; +/* *INDENT-ON* */ diff --git a/src/vnet/adj/adj_nsh.h b/src/vnet/adj/adj_nsh.h new file mode 100644 index 00000000..5501fbb9 --- /dev/null +++ b/src/vnet/adj/adj_nsh.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ADJ_NSH_H__ +#define __ADJ_NSH_H__ + +#include + +extern vlib_node_registration_t adj_nsh_midchain_node; +extern vlib_node_registration_t adj_nsh_rewrite_node; + +typedef struct _nsh_main_dummy +{ + u8 output_feature_arc_index; +} nsh_main_dummy_t; + +extern nsh_main_dummy_t nsh_main_dummy; + +#endif diff --git a/src/vnet/dpo/dpo.c b/src/vnet/dpo/dpo.c index cc2fa0eb..d8e075a7 100644 --- a/src/vnet/dpo/dpo.c +++ b/src/vnet/dpo/dpo.c @@ -98,6 +98,8 @@ vnet_link_to_dpo_proto (vnet_link_t linkt) return (DPO_PROTO_MPLS); case VNET_LINK_ETHERNET: return (DPO_PROTO_ETHERNET); + case VNET_LINK_NSH: + return (DPO_PROTO_NSH); case VNET_LINK_ARP: break; } diff --git a/src/vnet/dpo/dpo.h b/src/vnet/dpo/dpo.h index aff4e1b8..48b92d3d 100644 --- a/src/vnet/dpo/dpo.h +++ b/src/vnet/dpo/dpo.h @@ -67,9 +67,10 @@ typedef enum dpo_proto_t_ DPO_PROTO_IP6, DPO_PROTO_ETHERNET, DPO_PROTO_MPLS, + DPO_PROTO_NSH, } __attribute__((packed)) dpo_proto_t; -#define DPO_PROTO_NUM ((dpo_proto_t)(DPO_PROTO_MPLS+1)) +#define DPO_PROTO_NUM ((dpo_proto_t)(DPO_PROTO_NSH+1)) #define DPO_PROTO_NONE ((dpo_proto_t)(DPO_PROTO_NUM+1)) #define DPO_PROTOS { \ @@ -77,11 +78,12 @@ typedef enum dpo_proto_t_ [DPO_PROTO_IP6] = "ip6", \ [DPO_PROTO_ETHERNET] = "ethernet", \ [DPO_PROTO_MPLS] = "mpls", \ + [DPO_PROTO_NSH] = "nsh", \ } #define FOR_EACH_DPO_PROTO(_proto) \ for (_proto = DPO_PROTO_IP4; \ - _proto <= DPO_PROTO_MPLS; \ + _proto <= DPO_PROTO_NSH; \ _proto++) /** diff --git a/src/vnet/fib/fib_entry_delegate.c b/src/vnet/fib/fib_entry_delegate.c index efe402d1..70840b16 100644 --- a/src/vnet/fib/fib_entry_delegate.c +++ b/src/vnet/fib/fib_entry_delegate.c @@ -122,6 +122,8 @@ fib_entry_chain_type_to_delegate_type (fib_forward_chain_type_t fct) case FIB_FORW_CHAIN_TYPE_MCAST_IP4: case FIB_FORW_CHAIN_TYPE_MCAST_IP6: break; + case FIB_FORW_CHAIN_TYPE_NSH: + return (FIB_ENTRY_DELEGATE_CHAIN_NSH); } ASSERT(0); return (FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4); @@ -142,6 +144,8 @@ fib_entry_delegate_type_to_chain_type (fib_entry_delegate_type_t fdt) return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS); case FIB_ENTRY_DELEGATE_CHAIN_ETHERNET: return (FIB_FORW_CHAIN_TYPE_ETHERNET); + case FIB_ENTRY_DELEGATE_CHAIN_NSH: + return (FIB_FORW_CHAIN_TYPE_NSH); case FIB_ENTRY_DELEGATE_COVERED: case FIB_ENTRY_DELEGATE_ATTACHED_IMPORT: case FIB_ENTRY_DELEGATE_ATTACHED_EXPORT: diff --git a/src/vnet/fib/fib_entry_delegate.h b/src/vnet/fib/fib_entry_delegate.h index 6d3a6549..d9183c5f 100644 --- a/src/vnet/fib/fib_entry_delegate.h +++ b/src/vnet/fib/fib_entry_delegate.h @@ -35,6 +35,7 @@ typedef enum fib_entry_delegate_type_t_ { FIB_ENTRY_DELEGATE_CHAIN_MPLS_EOS = FIB_FORW_CHAIN_TYPE_MPLS_EOS, FIB_ENTRY_DELEGATE_CHAIN_MPLS_NON_EOS = FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, FIB_ENTRY_DELEGATE_CHAIN_ETHERNET = FIB_FORW_CHAIN_TYPE_ETHERNET, + FIB_ENTRY_DELEGATE_CHAIN_NSH = FIB_FORW_CHAIN_TYPE_NSH, /** * Dependency list of covered entries. * these are more specific entries that are interested in changes @@ -51,7 +52,7 @@ typedef enum fib_entry_delegate_type_t_ { #define FOR_EACH_DELEGATE_CHAIN(_entry, _fdt, _fed, _body) \ { \ for (_fdt = FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4; \ - _fdt <= FIB_ENTRY_DELEGATE_CHAIN_ETHERNET; \ + _fdt <= FIB_ENTRY_DELEGATE_CHAIN_NSH; \ _fdt++) \ { \ _fed = fib_entry_delegate_get(_entry, _fdt); \ diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index d54787cd..57109153 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -355,6 +355,7 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, break; } case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: ASSERT(0); break; } diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index 080057f3..aa545b5e 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -1755,6 +1755,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index, case FIB_FORW_CHAIN_TYPE_MPLS_EOS: case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: { adj_index_t ai; @@ -1787,6 +1788,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index, case FIB_FORW_CHAIN_TYPE_MCAST_IP4: case FIB_FORW_CHAIN_TYPE_MCAST_IP6: case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: ASSERT(0); break; } @@ -1809,6 +1811,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index, case FIB_FORW_CHAIN_TYPE_MCAST_IP4: case FIB_FORW_CHAIN_TYPE_MCAST_IP6: case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: ASSERT(0); break; } @@ -1824,6 +1827,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index, case FIB_FORW_CHAIN_TYPE_UNICAST_IP6: case FIB_FORW_CHAIN_TYPE_MPLS_EOS: case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: break; case FIB_FORW_CHAIN_TYPE_MCAST_IP4: case FIB_FORW_CHAIN_TYPE_MCAST_IP6: diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c index 3ecb38e8..2837a59d 100644 --- a/src/vnet/fib/fib_types.c +++ b/src/vnet/fib/fib_types.c @@ -279,6 +279,8 @@ fib_forw_chain_type_from_dpo_proto (dpo_proto_t proto) return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS); case DPO_PROTO_ETHERNET: return (FIB_FORW_CHAIN_TYPE_ETHERNET); + case DPO_PROTO_NSH: + return (FIB_FORW_CHAIN_TYPE_NSH); } ASSERT(0); return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); @@ -297,6 +299,8 @@ fib_forw_chain_type_to_link_type (fib_forward_chain_type_t fct) return (VNET_LINK_IP6); case FIB_FORW_CHAIN_TYPE_ETHERNET: return (VNET_LINK_ETHERNET); + case FIB_FORW_CHAIN_TYPE_NSH: + return (VNET_LINK_NSH); case FIB_FORW_CHAIN_TYPE_MPLS_EOS: /* * insufficient information to to convert @@ -322,6 +326,8 @@ fib_forw_chain_type_to_dpo_proto (fib_forward_chain_type_t fct) return (DPO_PROTO_IP6); case FIB_FORW_CHAIN_TYPE_ETHERNET: return (DPO_PROTO_ETHERNET); + case FIB_FORW_CHAIN_TYPE_NSH: + return (DPO_PROTO_NSH); case FIB_FORW_CHAIN_TYPE_MPLS_EOS: case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: return (DPO_PROTO_MPLS); diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index c51bc9c0..05e0e0af 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -105,10 +105,14 @@ typedef enum fib_forward_chain_type_t_ { FIB_FORW_CHAIN_TYPE_MCAST_IP6, /** * Contribute an object that is to be used to forward Ethernet packets. + */ + FIB_FORW_CHAIN_TYPE_ETHERNET, + /** + * Contribute an object that is to be used to forward NSH packets. * This is last in the list since it is not valid for many FIB objects, * and thus their array of per-chain-type DPOs can be sized smaller. */ - FIB_FORW_CHAIN_TYPE_ETHERNET, + FIB_FORW_CHAIN_TYPE_NSH, } __attribute__ ((packed)) fib_forward_chain_type_t; #define FIB_FORW_CHAINS { \ @@ -119,14 +123,15 @@ typedef enum fib_forward_chain_type_t_ { [FIB_FORW_CHAIN_TYPE_MCAST_IP6] = "multicast-ip6", \ [FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS] = "mpls-neos", \ [FIB_FORW_CHAIN_TYPE_MPLS_EOS] = "mpls-eos", \ + [FIB_FORW_CHAIN_TYPE_NSH] = "nsh", \ } -#define FIB_FORW_CHAIN_NUM (FIB_FORW_CHAIN_TYPE_MPLS_ETHERNET+1) +#define FIB_FORW_CHAIN_NUM (FIB_FORW_CHAIN_TYPE_NSH+1) #define FIB_FORW_CHAIN_MPLS_NUM (FIB_FORW_CHAIN_TYPE_MPLS_EOS+1) #define FOR_EACH_FIB_FORW_CHAIN(_item) \ for (_item = FIB_FORW_CHAIN_TYPE_UNICAST_IP4; \ - _item <= FIB_FORW_CHAIN_TYPE_ETHERNET; \ + _item <= FIB_FORW_CHAIN_TYPE_NSH; \ _item++) #define FOR_EACH_FIB_FORW_MPLS_CHAIN(_item) \ diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c index 0faed13e..cd43a3af 100644 --- a/src/vnet/gre/gre.c +++ b/src/vnet/gre/gre.c @@ -177,6 +177,9 @@ gre_proto_from_vnet_link (vnet_link_t link) return (GRE_PROTOCOL_teb); case VNET_LINK_ARP: return (GRE_PROTOCOL_arp); + case VNET_LINK_NSH: + ASSERT(0); + break; } ASSERT(0); return (GRE_PROTOCOL_ip4); diff --git a/src/vnet/interface.c b/src/vnet/interface.c index 9454ac18..2a1e70e8 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -1364,6 +1364,7 @@ vnet_link_to_l3_proto (vnet_link_t link) case VNET_LINK_ARP: return (VNET_L3_PACKET_TYPE_ARP); case VNET_LINK_ETHERNET: + case VNET_LINK_NSH: ASSERT (0); break; } diff --git a/src/vnet/interface.h b/src/vnet/interface.h index d42e5fda..7b791751 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -240,6 +240,7 @@ typedef enum vnet_link_t_ VNET_LINK_MPLS, VNET_LINK_ETHERNET, VNET_LINK_ARP, + VNET_LINK_NSH, } __attribute__ ((packed)) vnet_link_t; #define VNET_LINKS { \ @@ -248,13 +249,14 @@ typedef enum vnet_link_t_ [VNET_LINK_IP6] = "ipv6", \ [VNET_LINK_MPLS] = "mpls", \ [VNET_LINK_ARP] = "arp", \ + [VNET_LINK_NSH] = "nsh", \ } /** * @brief Number of link types. Not part of the enum so it does not have to be included in * switch statements */ -#define VNET_LINK_NUM (VNET_LINK_ARP+1) +#define VNET_LINK_NUM (VNET_LINK_NSH+1) /** * @brief Convert a link to to an Ethertype diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index cc73dfc5..f0383e16 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -2700,6 +2700,11 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, gid_address_vni (dst) = vni; gid_address_vni (src) = vni; } + else if (LISP_AFI_LCAF == type) + { + /* Eventually extend this to support NSH and other */ + ASSERT (0); + } } static uword @@ -2818,6 +2823,14 @@ lisp_cp_lookup_l2 (vlib_main_t * vm, return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_MAC)); } +static uword +lisp_cp_lookup_nsh (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * from_frame) +{ + /* TODO decide if NSH should be propagated as LCAF or not */ + return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_LCAF)); +} + /* *INDENT-OFF* */ VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = { .function = lisp_cp_lookup_ip4, @@ -2875,6 +2888,25 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node) = { }; /* *INDENT-ON* */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (lisp_cp_lookup_nsh_node) = { + .function = lisp_cp_lookup_nsh, + .name = "lisp-cp-lookup-nsh", + .vector_size = sizeof (u32), + .format_trace = format_lisp_cp_lookup_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = LISP_CP_LOOKUP_N_ERROR, + .error_strings = lisp_cp_lookup_error_strings, + + .n_next_nodes = LISP_CP_LOOKUP_N_NEXT, + + .next_nodes = { + [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + /* lisp_cp_input statistics */ #define foreach_lisp_cp_input_error \ _(DROP, "drop") \ diff --git a/src/vnet/lisp-cp/lisp_api.c b/src/vnet/lisp-cp/lisp_api.c index a877540b..78d32e17 100644 --- a/src/vnet/lisp-cp/lisp_api.c +++ b/src/vnet/lisp-cp/lisp_api.c @@ -714,6 +714,8 @@ fid_type_to_api_type (fid_address_t * fid) case FID_ADDR_MAC: return 2; + case FID_ADDR_NSH: + return 3; } return ~0; diff --git a/src/vnet/lisp-cp/lisp_cp_dpo.c b/src/vnet/lisp-cp/lisp_cp_dpo.c index 185b07a2..848f621e 100644 --- a/src/vnet/lisp-cp/lisp_cp_dpo.c +++ b/src/vnet/lisp-cp/lisp_cp_dpo.c @@ -79,12 +79,17 @@ const static char *const lisp_cp_ethernet_nodes[] = { NULL, }; +const static char *const lisp_cp_nsh_nodes[] = { + "lisp-cp-lookup-nsh", + NULL, +}; const static char *const *const lisp_cp_nodes[DPO_PROTO_NUM] = { [DPO_PROTO_IP4] = lisp_cp_ip4_nodes, [DPO_PROTO_IP6] = lisp_cp_ip6_nodes, [DPO_PROTO_ETHERNET] = lisp_cp_ethernet_nodes, [DPO_PROTO_MPLS] = NULL, + [DPO_PROTO_NSH] = lisp_cp_nsh_nodes, }; clib_error_t * diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index 748905d2..4a3d05b7 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -202,6 +202,20 @@ format_mac_address (u8 * s, va_list * args) a[0], a[1], a[2], a[3], a[4], a[5]); } +uword +unformat_nsh_address (unformat_input_t * input, va_list * args) +{ + nsh_t *a = va_arg (*args, nsh_t *); + return unformat (input, "SPI:%d SI:%d", &a->spi, &a->si); +} + +u8 * +format_nsh_address (u8 * s, va_list * args) +{ + nsh_t *a = va_arg (*args, nsh_t *); + return format (s, "SPI:%d SI:%d", a->spi, a->si); +} + u8 * format_fid_address (u8 * s, va_list * args) { @@ -211,9 +225,10 @@ format_fid_address (u8 * s, va_list * args) { case FID_ADDR_IP_PREF: return format (s, "%U", format_ip_prefix, &fid_addr_ippref (a)); - case FID_ADDR_MAC: return format (s, "%U", format_mac_address, &fid_addr_mac (a)); + case FID_ADDR_NSH: + return format (s, "%U", format_nsh_address, &fid_addr_nsh (a)); default: clib_warning ("Can't format fid address type %d!", fid_addr_type (a)); @@ -239,6 +254,8 @@ format_gid_address (u8 * s, va_list * args) case GID_ADDR_MAC: return format (s, "[%d] %U", gid_address_vni (a), format_mac_address, &gid_address_mac (a)); + case GID_ADDR_NSH: + return format (s, "%U", format_nsh_address, &gid_address_nsh (a)); default: clib_warning ("Can't format gid type %d", type); return 0; @@ -252,6 +269,7 @@ unformat_fid_address (unformat_input_t * i, va_list * args) fid_address_t *a = va_arg (*args, fid_address_t *); ip_prefix_t ippref; u8 mac[6] = { 0 }; + nsh_t nsh; if (unformat (i, "%U", unformat_ip_prefix, &ippref)) { @@ -263,6 +281,11 @@ unformat_fid_address (unformat_input_t * i, va_list * args) fid_addr_type (a) = FID_ADDR_MAC; mac_copy (fid_addr_mac (a), mac); } + else if (unformat (i, "%U", unformat_nsh_address, &nsh)) + { + fid_addr_type (a) = FID_ADDR_NSH; + nsh_copy (&fid_addr_nsh (a), mac); + } else return 0; @@ -301,6 +324,7 @@ unformat_gid_address (unformat_input_t * input, va_list * args) u8 mac[6] = { 0 }; ip_prefix_t ippref; fid_address_t sim1, sim2; + nsh_t nsh; memset (&ippref, 0, sizeof (ippref)); memset (&sim1, 0, sizeof (sim1)); @@ -323,6 +347,11 @@ unformat_gid_address (unformat_input_t * input, va_list * args) mac_copy (gid_address_mac (a), mac); gid_address_type (a) = GID_ADDR_MAC; } + else if (unformat (input, "%U", unformat_nsh_address, &nsh)) + { + nsh_copy (&gid_address_nsh (a), &nsh); + gid_address_type (a) = GID_ADDR_NSH; + } else return 0; @@ -588,6 +617,10 @@ fid_addr_parse (u8 * p, fid_address_t * a) case FID_ADDR_IP_PREF: return ip_address_parse (p, afi, ip_addr); + + case FID_ADDR_NSH: + ASSERT (0); + break; } return ~0; } @@ -917,6 +950,12 @@ mac_copy (void *dst, void *src) clib_memcpy (dst, src, 6); } +void +nsh_copy (void *dst, void *src) +{ + clib_memcpy (dst, src, sizeof (nsh_t)); +} + void sd_copy (void *dst, void *src) { @@ -1083,6 +1122,8 @@ fid_address_length (fid_address_t * a) return ip_prefix_length (&fid_addr_ippref (a)); case FID_ADDR_MAC: return 0; + case FID_ADDR_NSH: + return 0; } return 0; } diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index ac58b894..e43f5ab0 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -89,6 +89,7 @@ typedef enum GID_ADDR_LCAF, GID_ADDR_MAC, GID_ADDR_SRC_DST, + GID_ADDR_NSH, GID_ADDR_NO_ADDRESS, GID_ADDR_TYPES } gid_address_type_t; @@ -106,7 +107,8 @@ typedef enum typedef enum fid_addr_type_t_ { FID_ADDR_IP_PREF, - FID_ADDR_MAC + FID_ADDR_MAC, + FID_ADDR_NSH } __attribute__ ((packed)) fid_addr_type_t; /* flat address type */ @@ -116,6 +118,7 @@ typedef struct { ip_prefix_t ippref; u8 mac[6]; + u32 nsh; }; fid_addr_type_t type; } fid_address_t; @@ -124,6 +127,7 @@ typedef fid_address_t dp_address_t; #define fid_addr_ippref(_a) (_a)->ippref #define fid_addr_mac(_a) (_a)->mac +#define fid_addr_nsh(_a) (_a)->nsh #define fid_addr_type(_a) (_a)->type u8 *format_fid_address (u8 * s, va_list * args); @@ -153,6 +157,12 @@ typedef struct #define vni_mask_len(_a) (_a)->vni_mask_len #define vni_gid(_a) (_a)->gid_addr +typedef struct +{ + u32 spi; + u8 si; +} nsh_t; + typedef struct { /* the union needs to be at the beginning! */ @@ -177,6 +187,7 @@ typedef struct _gid_address_t lcaf_t lcaf; u8 mac[6]; source_dest_t sd; + nsh_t nsh; }; u8 type; u32 vni; @@ -232,6 +243,7 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); #define gid_address_ip_version(_a) ip_addr_version(&gid_address_ip(_a)) #define gid_address_lcaf(_a) (_a)->lcaf #define gid_address_mac(_a) (_a)->mac +#define gid_address_nsh(_a) (_a)->nsh #define gid_address_vni(_a) (_a)->vni #define gid_address_vni_mask(_a) (_a)->vni_mask #define gid_address_sd_dst_ippref(_a) sd_dst_ippref(&(_a)->sd) @@ -249,6 +261,7 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); _(ip_prefix) \ _(lcaf) \ _(mac) \ + _(nsh) \ _(sd) /* *INDENT-OFF* */ diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index 3288b241..d12dc362 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -201,7 +201,7 @@ VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = { typedef struct { - u32 lb_index; + u32 dpo_index; } l2_lisp_gpe_tx_trace_t; static u8 * @@ -211,7 +211,7 @@ format_l2_lisp_gpe_tx_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); l2_lisp_gpe_tx_trace_t *t = va_arg (*args, l2_lisp_gpe_tx_trace_t *); - s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->lb_index); + s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->dpo_index); return s; } @@ -278,7 +278,7 @@ l2_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, { l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->lb_index = lbi0; + tr->dpo_index = lbi0; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, l2_arc_to_lb); @@ -306,6 +306,110 @@ VNET_DEVICE_CLASS (l2_lisp_gpe_device_class,static) = { }; /* *INDENT-ON* */ +typedef struct +{ + u32 dpo_index; +} nsh_lisp_gpe_tx_trace_t; + +u8 * +format_nsh_lisp_gpe_tx_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + nsh_lisp_gpe_tx_trace_t *t = va_arg (*args, nsh_lisp_gpe_tx_trace_t *); + + s = format (s, "NSH-GPE-TX: tunnel %d", t->dpo_index); + return s; +} + +/** + * @brief LISP-GPE interface TX for NSH overlays. + * @node nsh_lisp_gpe_interface_tx + * + * The NSH LISP-GPE interface TX function. + * + * @param[in] vm vlib_main_t corresponding to the current thread. + * @param[in] node vlib_node_runtime_t data for this node. + * @param[in] frame vlib_frame_t whose contents should be dispatched. + * + * @return number of vectors in frame. + */ +static uword +nsh_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, next_index, *from, *to_next; + lisp_gpe_main_t *lgm = &lisp_gpe_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0; + u32 *nsh0, next0; + const dpo_id_t *dpo0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + nsh0 = vlib_buffer_get_current (b0); + + vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_LCAF; + + /* lookup SPI + SI (second word of the NSH header). + * NB: Load balancing was done by the control plane */ + dpo0 = lisp_nsh_fib_lookup (lgm, nsh0[1]); + + next0 = dpo0->dpoi_next_node; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + nsh_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, + sizeof (*tr)); + tr->dpo_index = dpo0->dpoi_index; + } + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return from_frame->n_vectors; +} + +static u8 * +format_nsh_lisp_gpe_name (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + return format (s, "nsh_lisp_gpe%d", dev_instance); +} + +/* *INDENT-OFF* */ +VNET_DEVICE_CLASS (nsh_lisp_gpe_device_class,static) = { + .name = "NSH_LISP_GPE", + .format_device_name = format_nsh_lisp_gpe_name, + .format_tx_trace = format_nsh_lisp_gpe_tx_trace, + .tx_function = nsh_lisp_gpe_interface_tx, +}; +/* *INDENT-ON* */ + static vnet_hw_interface_t * lisp_gpe_create_iface (lisp_gpe_main_t * lgm, u32 vni, u32 dp_table, vnet_device_class_t * dev_class, @@ -615,6 +719,72 @@ lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) lisp_gpe_remove_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces); } +/** + * @brief Add LISP-GPE NSH interface. + * + * Creates LISP-GPE interface, sets it in L3 mode. + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] a Parameters to create interface. + * + * @return sw_if_index. + */ +u32 +lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) +{ + vnet_main_t *vnm = lgm->vnet_main; + tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; + vnet_hw_interface_t *hi; + uword *hip, *si; + + hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); + + if (hip) + { + clib_warning ("NSH interface 0 already exists"); + return ~0; + } + + si = hash_get (nsh_ifaces->sw_if_index_by_vni, 0); + if (si) + { + clib_warning ("NSH interface already exists"); + return ~0; + } + + /* create lisp iface and populate tunnel tables */ + hi = lisp_gpe_create_iface (lgm, 0, 0, + &nsh_lisp_gpe_device_class, &lgm->nsh_ifaces); + + /* enable interface */ + vnet_sw_interface_set_flags (vnm, hi->sw_if_index, + VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_hw_interface_set_flags (vnm, hi->hw_if_index, + VNET_HW_INTERFACE_FLAG_LINK_UP); + + return (hi->sw_if_index); +} + +/** + * @brief Del LISP-GPE NSH interface. + * + */ +void +lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm) +{ + tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; + uword *hip; + + hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); + + if (hip == 0) + { + clib_warning ("The NSH 0 interface doesn't exist"); + return; + } + lisp_gpe_remove_iface (lgm, hip[0], 0, &lgm->nsh_ifaces); +} + static clib_error_t * lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -623,6 +793,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 is_add = 1; u32 table_id, vni, bd_id; u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0; + u8 nsh_iface = 0; if (vnet_lisp_gpe_enable_disable_status () == 0) { @@ -651,6 +822,10 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, { bd_index_is_set = 1; } + else if (unformat (line_input, "nsh")) + { + nsh_iface = 1; + } else { return clib_error_return (0, "parse error: '%U'", @@ -689,6 +864,21 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, lisp_gpe_tenant_l3_iface_unlock (vni); } + if (nsh_iface) + { + if (is_add) + { + if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main)) + { + return clib_error_return (0, "NSH interface not created"); + } + else + { + lisp_gpe_del_nsh_iface (&lisp_gpe_main); + } + } + } + return (NULL); } diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c index e78d45c9..e76c03f0 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.c +++ b/src/vnet/lisp-gpe/lisp_gpe.c @@ -151,6 +151,7 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, gid_address_copy (&a->lcl_eid, leid); gid_address_copy (&a->rmt_eid, reid); a->locator_pairs = pairs; + a->action = action; rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0); if (0 != rv) @@ -291,7 +292,6 @@ format_vnet_lisp_gpe_status (u8 * s, va_list * args) return format (s, "%s", lgm->is_en ? "enabled" : "disabled"); } - /** LISP-GPE init function. */ clib_error_t * lisp_gpe_init (vlib_main_t * vm) diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h index 3288c99f..e92df385 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.h +++ b/src/vnet/lisp-gpe/lisp_gpe.h @@ -119,6 +119,15 @@ typedef struct lisp_gpe_main /** Load-balance for a miss in the table */ dpo_id_t l2_lb_cp_lkup; + /* NSH data structures + * ================== */ + + BVT (clib_bihash) nsh_fib; + + tunnel_lookup_t nsh_ifaces; + + const dpo_id_t *nsh_cp_lkup; + /** convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c index 8c96a25c..1dbf8677 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c +++ b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c @@ -211,6 +211,8 @@ lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt) return (LISP_GPE_NEXT_PROTO_IP6); case VNET_LINK_ETHERNET: return (LISP_GPE_NEXT_PROTO_ETHERNET); + case VNET_LINK_NSH: + return (LISP_GPE_NEXT_PROTO_NSH); default: ASSERT (0); } @@ -254,14 +256,14 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) ladj = pool_elt_at_index (lisp_adj_pool, lai); lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); linkt = adj_get_link_type (ai); - adj_nbr_midchain_update_rewrite (ai, lisp_gpe_fixup, (VNET_LINK_ETHERNET == linkt ? ADJ_MIDCHAIN_FLAG_NO_COUNT : ADJ_MIDCHAIN_FLAG_NONE), - lisp_gpe_tunnel_build_rewrite - (lgt, ladj, lisp_gpe_adj_proto_from_vnet_link_type (linkt))); + lisp_gpe_tunnel_build_rewrite (lgt, ladj, + lisp_gpe_adj_proto_from_vnet_link_type + (linkt))); lisp_gpe_adj_stack_one (ladj, ai); } diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c index 7ad8679e..e51b585e 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c @@ -340,10 +340,14 @@ gid_to_dp_address (gid_address_t * g, dp_address_t * d) d->type = FID_ADDR_IP_PREF; break; case GID_ADDR_MAC: - default: mac_copy (&d->mac, &gid_address_mac (g)); d->type = FID_ADDR_MAC; break; + case GID_ADDR_NSH: + default: + d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si; + d->type = FID_ADDR_NSH; + break; } } @@ -671,7 +675,7 @@ del_l2_fwd_entry (lisp_gpe_main_t * lgm, } /** - * @brief Construct and insert the forwarding information used by a L2 entry + * @brief Construct and insert the forwarding information used by an L2 entry */ static void lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) @@ -688,7 +692,16 @@ lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) } else { - dpo_copy (&dpo, &lgm->l2_lb_cp_lkup); + switch (lfe->action) + { + case SEND_MAP_REQUEST: + dpo_copy (&dpo, &lgm->l2_lb_cp_lkup); + break; + case NO_ACTION: + case FORWARD_NATIVE: + case DROP: + dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_ETHERNET)); + } } /* add entry to l2 lisp fib */ @@ -784,6 +797,276 @@ add_l2_fwd_entry (lisp_gpe_main_t * lgm, return 0; } +/** + * @brief Lookup NSH SD FIB entry + * + * Does an SPI+SI lookup in the NSH LISP FIB. + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] spi_si SPI + SI. + * + * @return next node index. + */ +const dpo_id_t * +lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, u32 spi_si) +{ + int rv; + BVT (clib_bihash_kv) kv, value; + + memset (&kv, 0, sizeof (kv)); + kv.key[0] = spi_si; + rv = BV (clib_bihash_search_inline_2) (&lgm->nsh_fib, &kv, &value); + + if (rv != 0) + { + return lgm->nsh_cp_lkup; + } + else + { + lisp_gpe_fwd_entry_t *lfe; + lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, value.value); + return &lfe->nsh.choice; + } +} + +/** + * @brief Add/del NSH FIB entry + * + * Inserts value in NSH FIB keyed by SPI+SI. If entry is + * overwritten the associated value is returned. + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] spi_si SPI + SI. + * @param[in] dpo Load balanced mapped to SPI + SI + * + * @return ~0 or value of overwritten entry. + */ +static u32 +lisp_nsh_fib_add_del_entry (u32 spi_si, u32 lfei, u8 is_add) +{ + lisp_gpe_main_t *lgm = &lisp_gpe_main; + BVT (clib_bihash_kv) kv, value; + u32 old_val = ~0; + + memset (&kv, 0, sizeof (kv)); + kv.key[0] = spi_si; + kv.value = 0ULL; + + if (BV (clib_bihash_search) (&lgm->nsh_fib, &kv, &value) == 0) + old_val = value.value; + + if (!is_add) + BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 0 /* is_add */ ); + else + { + kv.value = lfei; + BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 1 /* is_add */ ); + } + return old_val; +} + +#define NSH_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) +#define NSH_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20) + +static void +nsh_fib_init (lisp_gpe_main_t * lgm) +{ + BV (clib_bihash_init) (&lgm->nsh_fib, "nsh fib", + 1 << max_log2 (NSH_FIB_DEFAULT_HASH_NUM_BUCKETS), + NSH_FIB_DEFAULT_HASH_MEMORY_SIZE); + + /* + * the result from a 'miss' in a NSH Table + */ + lgm->nsh_cp_lkup = lisp_cp_dpo_get (DPO_PROTO_NSH); +} + +static void +del_nsh_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) +{ + lisp_fwd_path_t *path; + + if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) + { + vec_foreach (path, lfe->paths) + { + lisp_gpe_adjacency_unlock (path->lisp_adj); + } + fib_path_list_child_remove (lfe->nsh.path_list_index, + lfe->nsh.child_index); + dpo_reset (&lfe->nsh.choice); + } + + lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), (u32) ~ 0, 0); + + hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); + clib_mem_free (lfe->key); + pool_put (lgm->lisp_fwd_entry_pool, lfe); +} + +/** + * @brief Delete LISP NSH forwarding entry. + * + * Coordinates the removal of forwarding entries for NSH LISP overlay: + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] a Parameters for building the forwarding entry. + * + * @return 0 on success. + */ +static int +del_nsh_fwd_entry (lisp_gpe_main_t * lgm, + vnet_lisp_gpe_add_del_fwd_entry_args_t * a) +{ + lisp_gpe_fwd_entry_key_t key; + lisp_gpe_fwd_entry_t *lfe; + + lfe = find_fwd_entry (lgm, a, &key); + + if (NULL == lfe) + return VNET_API_ERROR_INVALID_VALUE; + + del_nsh_fwd_entry_i (lgm, lfe); + + return (0); +} + +/** + * @brief Construct and insert the forwarding information used by an NSH entry + */ +static void +lisp_gpe_nsh_update_fwding (lisp_gpe_fwd_entry_t * lfe) +{ + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + dpo_id_t dpo = DPO_INVALID; + vnet_hw_interface_t *hi; + uword *hip; + + if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) + { + fib_path_list_contribute_forwarding (lfe->nsh.path_list_index, + FIB_FORW_CHAIN_TYPE_NSH, + &lfe->nsh.dpo); + + /* + * LISP encap is always the same for this SPI+SI so we do that hash now + * and stack on the choice. + */ + if (DPO_LOAD_BALANCE == lfe->nsh.dpo.dpoi_type) + { + const dpo_id_t *tmp; + const load_balance_t *lb; + int hash; + + lb = load_balance_get (lfe->nsh.dpo.dpoi_index); + hash = fid_addr_nsh (&lfe->key->rmt) % lb->lb_n_buckets; + tmp = + load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); + + dpo_copy (&dpo, tmp); + } + } + else + { + switch (lfe->action) + { + case SEND_MAP_REQUEST: + dpo_copy (&dpo, lgm->nsh_cp_lkup); + break; + case NO_ACTION: + case FORWARD_NATIVE: + case DROP: + dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_NSH)); + } + } + + /* We have only one nsh-lisp interface (no NSH virtualization) */ + hip = hash_get (lgm->nsh_ifaces.hw_if_index_by_dp_table, 0); + hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); + + dpo_stack_from_node (hi->tx_node_index, &lfe->nsh.choice, &dpo); + + /* add entry to nsh lisp fib */ + lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), + lfe - lgm->lisp_fwd_entry_pool, 1); + + dpo_reset (&dpo); +} + +/** + * @brief Add LISP NSH forwarding entry. + * + * Coordinates the creation of forwarding entries for L2 LISP overlay: + * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] a Parameters for building the forwarding entry. + * + * @return 0 on success. + */ +static int +add_nsh_fwd_entry (lisp_gpe_main_t * lgm, + vnet_lisp_gpe_add_del_fwd_entry_args_t * a) +{ + lisp_gpe_fwd_entry_key_t key; + lisp_gpe_fwd_entry_t *lfe; + + lfe = find_fwd_entry (lgm, a, &key); + + if (NULL != lfe) + /* don't support updates */ + return VNET_API_ERROR_INVALID_VALUE; + + pool_get (lgm->lisp_fwd_entry_pool, lfe); + memset (lfe, 0, sizeof (*lfe)); + lfe->key = clib_mem_alloc (sizeof (key)); + memcpy (lfe->key, &key, sizeof (key)); + + hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, + lfe - lgm->lisp_fwd_entry_pool); + + lfe->type = (a->is_negative ? + LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : + LISP_GPE_FWD_ENTRY_TYPE_NORMAL); + lfe->tenant = 0; + + if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) + { + fib_route_path_t *rpaths; + + /* + * Make the sorted array of LISP paths with their resp. adjacency + */ + lisp_gpe_fwd_entry_mk_paths (lfe, a); + + /* + * From the LISP paths, construct a FIB path list that will + * contribute a load-balance. + */ + rpaths = lisp_gpe_mk_fib_paths (lfe->paths); + + lfe->nsh.path_list_index = + fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, rpaths); + + /* + * become a child of the path-list so we receive updates when + * its forwarding state changes. this includes an implicit lock. + */ + lfe->nsh.child_index = + fib_path_list_child_add (lfe->nsh.path_list_index, + FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, + lfe - lgm->lisp_fwd_entry_pool); + } + else + { + lfe->action = a->action; + } + + lisp_gpe_nsh_update_fwding (lfe); + + return 0; +} + /** * @brief conver from the embedded fib_node_t struct to the LSIP entry */ @@ -802,7 +1085,12 @@ static fib_node_back_walk_rc_t lisp_gpe_fib_node_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx) { - lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_from_fib_node (node)); + lisp_gpe_fwd_entry_t *lfe = lisp_gpe_fwd_entry_from_fib_node (node); + + if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_MAC) + lisp_gpe_l2_update_fwding (lfe); + else if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_NSH) + lisp_gpe_nsh_update_fwding (lfe); return (FIB_NODE_BACK_WALK_CONTINUE); } @@ -877,6 +1165,11 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, return add_l2_fwd_entry (lgm, a); else return del_l2_fwd_entry (lgm, a); + case GID_ADDR_NSH: + if (a->is_add) + return add_nsh_fwd_entry (lgm, a); + else + return del_nsh_fwd_entry (lgm, a); default: clib_warning ("Forwarding entries for type %d not supported!", type); return -1; @@ -903,6 +1196,9 @@ vnet_lisp_gpe_fwd_entry_flush (void) case FID_ADDR_IP_PREF: del_ip_fwd_entry_i (lgm, lfe); break; + case FID_ADDR_NSH: + del_nsh_fwd_entry_i (lgm, lfe); + break; } })); /* *INDENT-ON* */ @@ -967,6 +1263,10 @@ format_lisp_gpe_fwd_entry (u8 * s, va_list ap) s = format (s, " fib-path-list:%d\n", lfe->l2.path_list_index); s = format (s, " dpo:%U\n", format_dpo_id, &lfe->l2.dpo, 0); break; + case FID_ADDR_NSH: + s = format (s, " fib-path-list:%d\n", lfe->nsh.path_list_index); + s = format (s, " dpo:%U\n", format_dpo_id, &lfe->nsh.dpo, 0); + break; case FID_ADDR_IP_PREF: break; } @@ -1036,6 +1336,7 @@ lisp_gpe_fwd_entry_init (vlib_main_t * vm) return (error); l2_fib_init (lgm); + nsh_fib_init (lgm); fib_node_register_type (FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, &lisp_fwd_vft); diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h index f7923671..d58895a3 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h @@ -81,7 +81,7 @@ typedef struct lisp_gpe_fwd_entry_t_ fib_node_t node; /** - * The Entry's key: {lEID,r-EID,vni} + * The Entry's key: {lEID,rEID,vni} */ lisp_gpe_fwd_entry_key_t *key; @@ -150,6 +150,33 @@ typedef struct lisp_gpe_fwd_entry_t_ */ dpo_id_t dpo; } l2; + + /** + * Fields relevant to an NSH entry + */ + struct + { + /** + * The path-list created for the forwarding + */ + fib_node_index_t path_list_index; + + /** + * Child index of this entry on the path-list + */ + u32 child_index; + + /** + * The DPO contributed by NSH + */ + dpo_id_t dpo; + + /** + * The DPO used for forwarding. Obtained after stacking tx node + * onto lb choice + */ + dpo_id_t choice; + } nsh; }; union @@ -177,6 +204,8 @@ extern void vnet_lisp_gpe_fwd_entry_flush (void); extern u32 lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, u16 bd_index, u8 src_mac[8], u8 dst_mac[8]); +extern const dpo_id_t *lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, + u32 spi_si); #endif /* diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index f1b6e8ee..acbe90bb 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -465,6 +465,7 @@ mfib_entry_src_collect_forwarding (fib_node_index_t pl_index, case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS: case FIB_FORW_CHAIN_TYPE_MPLS_EOS: case FIB_FORW_CHAIN_TYPE_ETHERNET: + case FIB_FORW_CHAIN_TYPE_NSH: ASSERT(0); break; } -- cgit 1.2.3-korg From a9a20e7f69f4a91a4d5267ab5ce14125bdc7d6c6 Mon Sep 17 00:00:00 2001 From: Billy McFall Date: Wed, 15 Feb 2017 11:39:12 -0500 Subject: VPP-635: CLI Memory leak with invalid parameter In the CLI parsing, below is a common pattern: /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "x")) x = 1; : else return clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); } unformat_free (line_input); The 'else' returns if an unknown string is encountered. There a memory leak because the 'unformat_free(line_input)' is not called. There is a large number of instances of this pattern. Replaced the previous pattern with: /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "x")) x = 1; : else { error = clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); goto done: } } /* ...Remaining code... */ done: unformat_free (line_input); return error; } In multiple files, 'unformat_free (line_input);' was never called, so there was a memory leak whether an invalid string was entered or not. Also, there were multiple instance where: error = clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); used 'input' as the last parameter instead of 'line_input'. The result is that output did not contain the substring in error, instead just an empty string. Fixed all of those as well. There are a lot of file, and very mind numbing work, so tried to keep it to a pattern to avoid mistakes. Change-Id: I8902f0c32a47dd7fb3bb3471a89818571702f1d2 Signed-off-by: Billy McFall Signed-off-by: Dave Barach --- build-root/emacs-lisp/tunnel-c-skel.el | 19 ++- src/plugins/ila/ila.c | 25 ++- src/plugins/lb/cli.c | 99 ++++++----- src/plugins/sixrd/sixrd.c | 42 +++-- src/plugins/snat/snat.c | 139 +++++++++++----- src/vlib/threads_cli.c | 79 ++++++--- src/vlib/trace.c | 13 +- src/vlib/unix/cli.c | 22 ++- src/vnet/devices/af_packet/cli.c | 56 +++++-- src/vnet/devices/dpdk/cli.c | 290 +++++++++++++++++++++++---------- src/vnet/devices/dpdk/ipsec/cli.c | 15 +- src/vnet/devices/netmap/cli.c | 54 ++++-- src/vnet/devices/virtio/vhost-user.c | 62 +++++-- src/vnet/gre/interface.c | 35 ++-- src/vnet/ip/ip4_source_check.c | 6 +- src/vnet/ip/ip4_test.c | 15 +- src/vnet/ip/ip6_neighbor.c | 27 ++- src/vnet/ip/lookup.c | 34 ++-- src/vnet/ipsec-gre/interface.c | 34 ++-- src/vnet/ipsec/ipsec_cli.c | 177 +++++++++++++------- src/vnet/l2/l2_patch.c | 26 ++- src/vnet/l2/l2_xcrw.c | 34 +++- src/vnet/l2tp/l2tp.c | 39 +++-- src/vnet/lisp-cp/lisp_cli.c | 139 ++++++++++++---- src/vnet/lisp-gpe/interface.c | 58 +++++-- src/vnet/lisp-gpe/lisp_gpe.c | 13 +- src/vnet/map/map.c | 186 +++++++++++++++------ src/vnet/mpls/mpls.c | 2 + src/vnet/mpls/mpls_tunnel.c | 19 ++- src/vnet/pg/cli.c | 39 +++-- src/vnet/policer/node_funcs.c | 19 ++- src/vnet/policer/policer.c | 13 +- src/vnet/unix/tapcli.c | 57 +++++-- src/vnet/vxlan-gpe/vxlan_gpe.c | 62 +++++-- src/vnet/vxlan/vxlan.c | 81 ++++++--- src/vpp/app/l2t.c | 9 +- src/vpp/app/vpe_cli.c | 24 ++- 37 files changed, 1487 insertions(+), 576 deletions(-) (limited to 'src/vnet/gre') diff --git a/build-root/emacs-lisp/tunnel-c-skel.el b/build-root/emacs-lisp/tunnel-c-skel.el index aa260e53..a1b1757d 100644 --- a/build-root/emacs-lisp/tunnel-c-skel.el +++ b/build-root/emacs-lisp/tunnel-c-skel.el @@ -288,6 +288,7 @@ static clib_error_t * vlib_cli_command_t * cmd) { unformat_input_t _line_input, * line_input = &_line_input; + clib_error_t *error = 0; ip4_address_t src, dst; u8 is_add = 1; u8 src_set = 0; @@ -322,13 +323,19 @@ static clib_error_t * { encap_fib_index = fib_index_from_fib_id (tmp); if (encap_fib_index == ~0) - return clib_error_return (0, \"nonexistent encap fib id %d\", tmp); + { + unformat_free (line_input); + return clib_error_return (0, \"nonexistent encap fib id %d\", tmp); + } } else if (unformat (line_input, \"decap-vrf-id %d\", &tmp)) { decap_fib_index = fib_index_from_fib_id (tmp); if (decap_fib_index == ~0) - return clib_error_return (0, \"nonexistent decap fib id %d\", tmp); + { + unformat_free (line_input); + return clib_error_return (0, \"nonexistent decap fib id %d\", tmp); + } } else if (unformat (line_input, \"decap-next %U\", unformat_decap_next, &decap_next_index)) @@ -346,8 +353,12 @@ static clib_error_t * * in the " ENCAP_STACK " header */ else - return clib_error_return (0, \"parse error: '%U'\", - format_unformat_error, line_input); + { + error = clib_error_return (0, \"parse error: '%U'\", + format_unformat_error, line_input); + unformat_free (line_input); + return error; + } } unformat_free (line_input); diff --git a/src/plugins/ila/ila.c b/src/plugins/ila/ila.c index e0f3907f..52c7ea55 100644 --- a/src/plugins/ila/ila.c +++ b/src/plugins/ila/ila.c @@ -949,6 +949,7 @@ ila_entry_command_fn (vlib_main_t * vm, ila_add_del_entry_args_t args = { 0 }; u8 next_hop_set = 0; int ret; + clib_error_t *error = 0; args.type = ILA_TYPE_IID; args.csum_mode = ILA_CSUM_MODE_NO_ACTION; @@ -986,19 +987,29 @@ ila_entry_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) args.is_del = 1; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (!next_hop_set) - return clib_error_return (0, "Specified a next hop"); + { + error = clib_error_return (0, "Specified a next hop"); + goto done; + } if ((ret = ila_add_del_entry (&args))) - return clib_error_return (0, "ila_add_del_entry returned error %d", ret); + { + error = clib_error_return (0, "ila_add_del_entry returned error %d", ret); + goto done; + } - return NULL; +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (ila_entry_command, static) = diff --git a/src/plugins/lb/cli.c b/src/plugins/lb/cli.c index b59c6426..6452a875 100644 --- a/src/plugins/lb/cli.c +++ b/src/plugins/lb/cli.c @@ -28,13 +28,16 @@ lb_vip_command_fn (vlib_main_t * vm, int ret; u32 gre4 = 0; lb_vip_type_t type; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; - if (!unformat(line_input, "%U", unformat_ip46_prefix, &prefix, &plen, IP46_TYPE_ANY, &plen)) - return clib_error_return (0, "invalid vip prefix: '%U'", - format_unformat_error, line_input); + if (!unformat(line_input, "%U", unformat_ip46_prefix, &prefix, &plen, IP46_TYPE_ANY, &plen)) { + error = clib_error_return (0, "invalid vip prefix: '%U'", + format_unformat_error, line_input); + goto done; + } while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -46,13 +49,13 @@ lb_vip_command_fn (vlib_main_t * vm, gre4 = 1; else if (unformat(line_input, "encap gre6")) gre4 = 0; - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + else { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (ip46_prefix_is_ip4(&prefix, plen)) { type = (gre4)?LB_VIP_TYPE_IP4_GRE4:LB_VIP_TYPE_IP4_GRE6; @@ -65,17 +68,25 @@ lb_vip_command_fn (vlib_main_t * vm, u32 index; if (!del) { if ((ret = lb_vip_add(&prefix, plen, type, new_len, &index))) { - return clib_error_return (0, "lb_vip_add error %d", ret); + error = clib_error_return (0, "lb_vip_add error %d", ret); + goto done; } else { vlib_cli_output(vm, "lb_vip_add ok %d", index); } } else { - if ((ret = lb_vip_find_index(&prefix, plen, &index))) - return clib_error_return (0, "lb_vip_find_index error %d", ret); - else if ((ret = lb_vip_del(index))) - return clib_error_return (0, "lb_vip_del error %d", ret); + if ((ret = lb_vip_find_index(&prefix, plen, &index))) { + error = clib_error_return (0, "lb_vip_find_index error %d", ret); + goto done; + } else if ((ret = lb_vip_del(index))) { + error = clib_error_return (0, "lb_vip_del error %d", ret); + goto done; + } } - return NULL; + +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (lb_vip_command, static) = @@ -96,16 +107,21 @@ lb_as_command_fn (vlib_main_t * vm, u32 vip_index; u8 del = 0; int ret; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; - if (!unformat(line_input, "%U", unformat_ip46_prefix, &vip_prefix, &vip_plen, IP46_TYPE_ANY)) - return clib_error_return (0, "invalid as address: '%U'", - format_unformat_error, line_input); + if (!unformat(line_input, "%U", unformat_ip46_prefix, &vip_prefix, &vip_plen, IP46_TYPE_ANY)) { + error = clib_error_return (0, "invalid as address: '%U'", + format_unformat_error, line_input); + goto done; + } - if ((ret = lb_vip_find_index(&vip_prefix, vip_plen, &vip_index))) - return clib_error_return (0, "lb_vip_find_index error %d", ret); + if ((ret = lb_vip_find_index(&vip_prefix, vip_plen, &vip_index))) { + error = clib_error_return (0, "lb_vip_find_index error %d", ret); + goto done; + } while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -114,15 +130,15 @@ lb_as_command_fn (vlib_main_t * vm, } else if (unformat(line_input, "del")) { del = 1; } else { - vec_free(as_array); - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; } } if (!vec_len(as_array)) { - vec_free(as_array); - return clib_error_return (0, "No AS address provided"); + error = clib_error_return (0, "No AS address provided"); + goto done; } lb_garbage_collection(); @@ -130,18 +146,21 @@ lb_as_command_fn (vlib_main_t * vm, if (del) { if ((ret = lb_vip_del_ass(vip_index, as_array, vec_len(as_array)))) { - vec_free(as_array); - return clib_error_return (0, "lb_vip_del_ass error %d", ret); + error = clib_error_return (0, "lb_vip_del_ass error %d", ret); + goto done; } } else { if ((ret = lb_vip_add_ass(vip_index, as_array, vec_len(as_array)))) { - vec_free(as_array); - return clib_error_return (0, "lb_vip_add_ass error %d", ret); + error = clib_error_return (0, "lb_vip_add_ass error %d", ret); + goto done; } } +done: + unformat_free (line_input); vec_free(as_array); - return 0; + + return error; } VLIB_CLI_COMMAND (lb_as_command, static) = @@ -163,6 +182,7 @@ lb_conf_command_fn (vlib_main_t * vm, u32 per_cpu_sticky_buckets_log2 = 0; u32 flow_timeout = lbm->flow_timeout; int ret; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -181,19 +201,24 @@ lb_conf_command_fn (vlib_main_t * vm, per_cpu_sticky_buckets = 1 << per_cpu_sticky_buckets_log2; } else if (unformat(line_input, "timeout %d", &flow_timeout)) ; - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + else { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - lb_garbage_collection(); - if ((ret = lb_conf(&ip4, &ip6, per_cpu_sticky_buckets, flow_timeout))) - return clib_error_return (0, "lb_conf error %d", ret); + if ((ret = lb_conf(&ip4, &ip6, per_cpu_sticky_buckets, flow_timeout))) { + error = clib_error_return (0, "lb_conf error %d", ret); + goto done; + } - return NULL; +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (lb_conf_command, static) = diff --git a/src/plugins/sixrd/sixrd.c b/src/plugins/sixrd/sixrd.c index 71fc181f..67a9a3ad 100644 --- a/src/plugins/sixrd/sixrd.c +++ b/src/plugins/sixrd/sixrd.c @@ -192,6 +192,7 @@ sixrd_add_domain_command_fn (vlib_main_t *vm, u32 num_m_args = 0; /* Optional arguments */ u32 mtu = 0; + clib_error_t *error = 0; /* Get a line of input. */ if (!unformat_user(input, unformat_line_input, line_input)) @@ -205,19 +206,25 @@ sixrd_add_domain_command_fn (vlib_main_t *vm, num_m_args++; else if (unformat(line_input, "mtu %d", &mtu)) num_m_args++; - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); + else { + error = clib_error_return(0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free(line_input); - if (num_m_args < 3) - return clib_error_return(0, "mandatory argument(s) missing"); + if (num_m_args < 3) { + error = clib_error_return(0, "mandatory argument(s) missing"); + goto done; + } sixrd_create_domain(&ip6_prefix, ip6_prefix_len, &ip4_prefix, ip4_prefix_len, &ip4_src, &sixrd_domain_index, mtu); - return 0; +done: + unformat_free (line_input); + + return error; } static clib_error_t * @@ -228,6 +235,7 @@ sixrd_del_domain_command_fn (vlib_main_t *vm, unformat_input_t _line_input, *line_input = &_line_input; u32 num_m_args = 0; u32 sixrd_domain_index; + clib_error_t *error = 0; /* Get a line of input. */ if (! unformat_user(input, unformat_line_input, line_input)) @@ -236,18 +244,24 @@ sixrd_del_domain_command_fn (vlib_main_t *vm, while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) { if (unformat(line_input, "index %d", &sixrd_domain_index)) num_m_args++; - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); + else { + error = clib_error_return(0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free(line_input); - if (num_m_args != 1) - return clib_error_return(0, "mandatory argument(s) missing"); + if (num_m_args != 1) { + error = clib_error_return(0, "mandatory argument(s) missing"); + goto done; + } sixrd_delete_domain(sixrd_domain_index); - return 0; +done: + unformat_free (line_input); + + return error; } static u8 * diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index 73854a7a..8c2bacdb 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -1705,6 +1705,7 @@ add_address_command_fn (vlib_main_t * vm, int i, count; int is_add = 1; int rv = 0; + clib_error_t *error = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -1721,19 +1722,27 @@ add_address_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) is_add = 0; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (sm->static_mapping_only) - return clib_error_return (0, "static mapping only mode"); + { + error = clib_error_return (0, "static mapping only mode"); + goto done; + } start_host_order = clib_host_to_net_u32 (start_addr.as_u32); end_host_order = clib_host_to_net_u32 (end_addr.as_u32); if (end_host_order < start_host_order) - return clib_error_return (0, "end address less than start address"); + { + error = clib_error_return (0, "end address less than start address"); + goto done; + } count = (end_host_order - start_host_order) + 1; @@ -1755,11 +1764,11 @@ add_address_command_fn (vlib_main_t * vm, switch (rv) { case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "S-NAT address not exist."); - break; + error = clib_error_return (0, "S-NAT address not exist."); + goto done; case VNET_API_ERROR_UNSPECIFIED: - return clib_error_return (0, "S-NAT address used in static mapping."); - break; + error = clib_error_return (0, "S-NAT address used in static mapping."); + goto done; default: break; } @@ -1767,7 +1776,10 @@ add_address_command_fn (vlib_main_t * vm, increment_v4_address (&this_addr); } - return 0; +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (add_address_command, static) = { @@ -1807,10 +1819,12 @@ snat_feature_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) is_del = 1; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (vec_len (inside_sw_if_indices)) { @@ -1830,6 +1844,8 @@ snat_feature_command_fn (vlib_main_t * vm, } } +done: + unformat_free (line_input); vec_free (inside_sw_if_indices); vec_free (outside_sw_if_indices); @@ -1923,13 +1939,18 @@ add_static_mapping_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) is_add = 0; else - return clib_error_return (0, "unknown input: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (!addr_only && !proto_set) - return clib_error_return (0, "missing protocol"); + { + error = clib_error_return (0, "missing protocol"); + goto done; + } rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port, vrf_id, addr_only, sw_if_index, proto, is_add); @@ -1937,22 +1958,27 @@ add_static_mapping_command_fn (vlib_main_t * vm, switch (rv) { case VNET_API_ERROR_INVALID_VALUE: - return clib_error_return (0, "External port already in use."); - break; + error = clib_error_return (0, "External port already in use."); + goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: if (is_add) - return clib_error_return (0, "External addres must be allocated."); + error = clib_error_return (0, "External addres must be allocated."); else - return clib_error_return (0, "Mapping not exist."); - break; + error = clib_error_return (0, "Mapping not exist."); + goto done; case VNET_API_ERROR_NO_SUCH_FIB: - return clib_error_return (0, "No such VRF id."); + error = clib_error_return (0, "No such VRF id."); + goto done; case VNET_API_ERROR_VALUE_EXIST: - return clib_error_return (0, "Mapping already exist."); + error = clib_error_return (0, "Mapping already exist."); + goto done; default: break; } +done: + unformat_free (line_input); + return error; } @@ -1985,6 +2011,7 @@ set_workers_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; uword *bitmap = 0; int rv = 0; + clib_error_t *error = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -1995,13 +2022,18 @@ set_workers_command_fn (vlib_main_t * vm, if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap)) ; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (bitmap == 0) - return clib_error_return (0, "List of workers must be specified."); + { + error = clib_error_return (0, "List of workers must be specified."); + goto done; + } rv = snat_set_workers(bitmap); @@ -2010,17 +2042,20 @@ set_workers_command_fn (vlib_main_t * vm, switch (rv) { case VNET_API_ERROR_INVALID_WORKER: - return clib_error_return (0, "Invalid worker(s)."); - break; + error = clib_error_return (0, "Invalid worker(s)."); + goto done; case VNET_API_ERROR_FEATURE_DISABLED: - return clib_error_return (0, + error = clib_error_return (0, "Supported only if 2 or more workes available."); - break; + goto done; default: break; } - return 0; +done: + unformat_free (line_input); + + return error; } /*? @@ -2047,6 +2082,7 @@ snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm, u32 src_port = 0; u8 enable = 1; int rv = 0; + clib_error_t *error = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2061,17 +2097,25 @@ snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm, else if (unformat (line_input, "disable")) enable = 0; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port); if (rv) - return clib_error_return (0, "ipfix logging enable failed"); + { + error = clib_error_return (0, "ipfix logging enable failed"); + goto done; + } - return 0; +done: + unformat_free (line_input); + + return error; } /*? @@ -2604,6 +2648,7 @@ snat_add_interface_address_command_fn (vlib_main_t * vm, u32 sw_if_index; int rv; int is_del = 0; + clib_error_t *error = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2617,8 +2662,11 @@ snat_add_interface_address_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) is_del = 1; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } rv = snat_add_interface_address (sm, sw_if_index, is_del); @@ -2629,10 +2677,15 @@ snat_add_interface_address_command_fn (vlib_main_t * vm, break; default: - return clib_error_return (0, "snat_add_interface_address returned %d", - rv); + error = clib_error_return (0, "snat_add_interface_address returned %d", + rv); + goto done; } - return 0; + +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = { diff --git a/src/vlib/threads_cli.c b/src/vlib/threads_cli.c index 54cc1aed..36f8109e 100644 --- a/src/vlib/threads_cli.c +++ b/src/vlib/threads_cli.c @@ -163,21 +163,31 @@ trace_frame_queue (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "index %u", &index)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (enable > 1) - return clib_error_return (0, "expecting on or off"); + { + error = clib_error_return (0, "expecting on or off"); + goto done; + } if (vec_len (tm->frame_queue_mains) == 0) - return clib_error_return (0, "no worker handoffs exist"); + { + error = clib_error_return (0, "no worker handoffs exist"); + goto done; + } if (index > vec_len (tm->frame_queue_mains) - 1) - return clib_error_return (0, - "expecting valid worker handoff queue index"); + { + error = clib_error_return (0, + "expecting valid worker handoff queue index"); + goto done; + } fqm = vec_elt_at_index (tm->frame_queue_mains, index); @@ -185,7 +195,7 @@ trace_frame_queue (vlib_main_t * vm, unformat_input_t * input, if (num_fq == 0) { vlib_cli_output (vm, "No frame queues exist\n"); - return error; + goto done; } // Allocate storage for trace if necessary @@ -204,6 +214,10 @@ trace_frame_queue (vlib_main_t * vm, unformat_input_t * input, memset (fqh, 0, sizeof (*fqh)); fqm->vlib_frame_queues[fqix]->trace = enable; } + +done: + unformat_free (line_input); + return error; } @@ -432,28 +446,33 @@ test_frame_queue_nelts (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "index %u", &index)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (index > vec_len (tm->frame_queue_mains) - 1) - return clib_error_return (0, - "expecting valid worker handoff queue index"); + { + error = clib_error_return (0, + "expecting valid worker handoff queue index"); + goto done; + } fqm = vec_elt_at_index (tm->frame_queue_mains, index); if ((nelts != 4) && (nelts != 8) && (nelts != 16) && (nelts != 32)) { - return clib_error_return (0, "expecting 4,8,16,32"); + error = clib_error_return (0, "expecting 4,8,16,32"); + goto done; } num_fq = vec_len (fqm->vlib_frame_queues); if (num_fq == 0) { vlib_cli_output (vm, "No frame queues exist\n"); - return error; + goto done; } for (fqix = 0; fqix < num_fq; fqix++) @@ -461,6 +480,9 @@ test_frame_queue_nelts (vlib_main_t * vm, unformat_input_t * input, fqm->vlib_frame_queues[fqix]->nelts = nelts; } +done: + unformat_free (line_input); + return error; } @@ -499,15 +521,19 @@ test_frame_queue_threshold (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "index %u", &index)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (index > vec_len (tm->frame_queue_mains) - 1) - return clib_error_return (0, - "expecting valid worker handoff queue index"); + { + error = clib_error_return (0, + "expecting valid worker handoff queue index"); + goto done; + } fqm = vec_elt_at_index (tm->frame_queue_mains, index); @@ -515,7 +541,7 @@ test_frame_queue_threshold (vlib_main_t * vm, unformat_input_t * input, if (threshold == ~(u32) 0) { vlib_cli_output (vm, "expecting threshold value\n"); - return error; + goto done; } if (threshold == 0) @@ -525,7 +551,7 @@ test_frame_queue_threshold (vlib_main_t * vm, unformat_input_t * input, if (num_fq == 0) { vlib_cli_output (vm, "No frame queues exist\n"); - return error; + goto done; } for (fqix = 0; fqix < num_fq; fqix++) @@ -533,6 +559,9 @@ test_frame_queue_threshold (vlib_main_t * vm, unformat_input_t * input, fqm->vlib_frame_queues[fqix]->vector_threshold = threshold; } +done: + unformat_free (line_input); + return error; } diff --git a/src/vlib/trace.c b/src/vlib/trace.c index dcdb837f..6d487ae1 100644 --- a/src/vlib/trace.c +++ b/src/vlib/trace.c @@ -372,6 +372,7 @@ cli_add_trace_buffer (vlib_main_t * vm, vlib_trace_node_t *tn; u32 node_index, add; u8 verbose = 0; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -384,8 +385,11 @@ cli_add_trace_buffer (vlib_main_t * vm, else if (unformat (line_input, "verbose")) verbose = 1; else - return clib_error_create ("expected NODE COUNT, got `%U'", - format_unformat_error, line_input); + { + error = clib_error_create ("expected NODE COUNT, got `%U'", + format_unformat_error, line_input); + goto done; + } } /* *INDENT-OFF* */ @@ -403,7 +407,10 @@ cli_add_trace_buffer (vlib_main_t * vm, })); /* *INDENT-ON* */ - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vlib/unix/cli.c b/src/vlib/unix/cli.c index 69fca6ec..88e2453c 100644 --- a/src/vlib/unix/cli.c +++ b/src/vlib/unix/cli.c @@ -2835,6 +2835,7 @@ unix_cli_set_terminal_pager (vlib_main_t * vm, unix_cli_main_t *cm = &unix_cli_main; unix_cli_file_t *cf; unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -2852,13 +2853,17 @@ unix_cli_set_terminal_pager (vlib_main_t * vm, "Pager limit set to %u lines; note, this is global.\n", um->cli_pager_buffer_limit); else - return clib_error_return (0, "unknown parameter: `%U`", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown parameter: `%U`", + format_unformat_error, line_input); + goto done; + } } +done: unformat_free (line_input); - return 0; + return error; } /*? @@ -2886,6 +2891,7 @@ unix_cli_set_terminal_history (vlib_main_t * vm, unix_cli_file_t *cf; unformat_input_t _line_input, *line_input = &_line_input; u32 limit; + clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -2901,8 +2907,11 @@ unix_cli_set_terminal_history (vlib_main_t * vm, else if (unformat (line_input, "limit %u", &cf->history_limit)) ; else - return clib_error_return (0, "unknown parameter: `%U`", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown parameter: `%U`", + format_unformat_error, line_input); + goto done; + } /* If we reduced history size, or turned it off, purge the history */ limit = cf->has_history ? cf->history_limit : 0; @@ -2914,9 +2923,10 @@ unix_cli_set_terminal_history (vlib_main_t * vm, } } +done: unformat_free (line_input); - return 0; + return error; } /*? diff --git a/src/vnet/devices/af_packet/cli.c b/src/vnet/devices/af_packet/cli.c index 6baa26e1..d4aa7016 100644 --- a/src/vnet/devices/af_packet/cli.c +++ b/src/vnet/devices/af_packet/cli.c @@ -49,6 +49,7 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 *hw_addr_ptr = 0; u32 sw_if_index; int r; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -63,29 +64,47 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input, (line_input, "hw-addr %U", unformat_ethernet_address, hwaddr)) hw_addr_ptr = hwaddr; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (host_if_name == NULL) - return clib_error_return (0, "missing host interface name"); + { + error = clib_error_return (0, "missing host interface name"); + goto done; + } r = af_packet_create_if (vm, host_if_name, hw_addr_ptr, &sw_if_index); - vec_free (host_if_name); if (r == VNET_API_ERROR_SYSCALL_ERROR_1) - return clib_error_return (0, "%s (errno %d)", strerror (errno), errno); + { + error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno); + goto done; + } if (r == VNET_API_ERROR_INVALID_INTERFACE) - return clib_error_return (0, "Invalid interface name"); + { + error = clib_error_return (0, "Invalid interface name"); + goto done; + } if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS) - return clib_error_return (0, "Interface elready exists"); + { + error = clib_error_return (0, "Interface elready exists"); + goto done; + } vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index); - return 0; + +done: + vec_free (host_if_name); + unformat_free (line_input); + + return error; } /*? @@ -124,6 +143,7 @@ af_packet_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, { unformat_input_t _line_input, *line_input = &_line_input; u8 *host_if_name = NULL; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -134,18 +154,26 @@ af_packet_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, if (unformat (line_input, "name %s", &host_if_name)) ; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (host_if_name == NULL) - return clib_error_return (0, "missing host interface name"); + { + error = clib_error_return (0, "missing host interface name"); + goto done; + } af_packet_delete_if (vm, host_if_name); + +done: vec_free (host_if_name); + unformat_free (line_input); - return 0; + return error; } /*? diff --git a/src/vnet/devices/dpdk/cli.c b/src/vnet/devices/dpdk/cli.c index d133cfd9..1fc665ac 100644 --- a/src/vnet/devices/dpdk/cli.c +++ b/src/vnet/devices/dpdk/cli.c @@ -398,7 +398,7 @@ set_dpdk_if_desc (vlib_main_t * vm, unformat_input_t * input, u32 hw_if_index = (u32) ~ 0; u32 nb_rx_desc = (u32) ~ 0; u32 nb_tx_desc = (u32) ~ 0; - clib_error_t *rv; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -414,25 +414,37 @@ set_dpdk_if_desc (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "rx %d", &nb_rx_desc)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); if ((xd->flags & DPDK_DEVICE_FLAG_PMD) == 0) - return clib_error_return (0, "number of descriptors can be set only for " - "physical devices"); + { + error = + clib_error_return (0, + "number of descriptors can be set only for " + "physical devices"); + goto done; + } if ((nb_rx_desc == (u32) ~ 0 || nb_rx_desc == xd->nb_rx_desc) && (nb_tx_desc == (u32) ~ 0 || nb_tx_desc == xd->nb_tx_desc)) - return clib_error_return (0, "nothing changed"); + { + error = clib_error_return (0, "nothing changed"); + goto done; + } if (nb_rx_desc != (u32) ~ 0) xd->nb_rx_desc = nb_rx_desc; @@ -440,9 +452,12 @@ set_dpdk_if_desc (vlib_main_t * vm, unformat_input_t * input, if (nb_tx_desc != (u32) ~ 0) xd->nb_tx_desc = nb_tx_desc; - rv = dpdk_port_setup (dm, xd); + error = dpdk_port_setup (dm, xd); + +done: + unformat_free (line_input); - return rv; + return error; } /* *INDENT-OFF* */ @@ -523,6 +538,7 @@ set_dpdk_if_placement (vlib_main_t * vm, unformat_input_t * input, u32 queue = (u32) 0; u32 cpu = (u32) ~ 0; int i; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -538,18 +554,25 @@ set_dpdk_if_placement (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "thread %d", &cpu)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } if (cpu < dm->input_cpu_first_index || cpu >= (dm->input_cpu_first_index + dm->input_cpu_count)) - return clib_error_return (0, "please specify valid thread id"); + { + error = clib_error_return (0, "please specify valid thread id"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -563,7 +586,7 @@ set_dpdk_if_placement (vlib_main_t * vm, unformat_input_t * input, queue == dq->queue_id) { if (cpu == i) /* nothing to do */ - return 0; + goto done; vec_del1(dm->devices_by_cpu[i], dq - dm->devices_by_cpu[i]); vec_add2(dm->devices_by_cpu[cpu], dq, 1); @@ -586,13 +609,18 @@ set_dpdk_if_placement (vlib_main_t * vm, unformat_input_t * input, vlib_node_set_state (vlib_mains[cpu], dpdk_input_node.index, VLIB_NODE_STATE_POLLING); - return 0; + goto done; } } /* *INDENT-ON* */ } - return clib_error_return (0, "not found"); + error = clib_error_return (0, "not found"); + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -653,6 +681,7 @@ set_dpdk_if_hqos_placement (vlib_main_t * vm, unformat_input_t * input, u32 hw_if_index = (u32) ~ 0; u32 cpu = (u32) ~ 0; int i; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -666,18 +695,22 @@ set_dpdk_if_hqos_placement (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "thread %d", &cpu)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) return clib_error_return (0, "please specify valid interface name"); if (cpu < dm->hqos_cpu_first_index || cpu >= (dm->hqos_cpu_first_index + dm->hqos_cpu_count)) - return clib_error_return (0, "please specify valid thread id"); + { + error = clib_error_return (0, "please specify valid thread id"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -689,7 +722,7 @@ set_dpdk_if_hqos_placement (vlib_main_t * vm, unformat_input_t * input, if (hw_if_index == dm->devices[dq->device].vlib_hw_if_index) { if (cpu == i) /* nothing to do */ - return 0; + goto done; vec_del1 (dm->devices_by_hqos_cpu[i], dq - dm->devices_by_hqos_cpu[i]); @@ -703,12 +736,17 @@ set_dpdk_if_hqos_placement (vlib_main_t * vm, unformat_input_t * input, vec_sort_with_function (dm->devices_by_hqos_cpu[cpu], dpdk_device_queue_sort); - return 0; + goto done; } } } - return clib_error_return (0, "not found"); + error = clib_error_return (0, "not found"); + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -732,6 +770,7 @@ set_dpdk_if_hqos_pipe (vlib_main_t * vm, unformat_input_t * input, u32 pipe_id = (u32) ~ 0; u32 profile_id = (u32) ~ 0; int rv; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -749,14 +788,18 @@ set_dpdk_if_hqos_pipe (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "profile %d", &profile_id)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -765,9 +808,15 @@ set_dpdk_if_hqos_pipe (vlib_main_t * vm, unformat_input_t * input, rte_sched_pipe_config (xd->hqos_ht->hqos, subport_id, pipe_id, profile_id); if (rv) - return clib_error_return (0, "pipe configuration failed"); + { + error = clib_error_return (0, "pipe configuration failed"); + goto done; + } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -797,6 +846,7 @@ set_dpdk_if_hqos_subport (vlib_main_t * vm, unformat_input_t * input, .tc_period = 10, }; int rv; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -829,23 +879,33 @@ set_dpdk_if_hqos_subport (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "period %d", &p.tc_period)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport_id, &p); if (rv) - return clib_error_return (0, "subport configuration failed"); + { + error = clib_error_return (0, "subport configuration failed"); + goto done; + } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -872,6 +932,7 @@ set_dpdk_if_hqos_tctbl (vlib_main_t * vm, unformat_input_t * input, u32 queue = (u32) ~ 0; u32 entry = (u32) ~ 0; u32 val, i; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -889,20 +950,33 @@ set_dpdk_if_hqos_tctbl (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "queue %d", &queue)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } if (entry >= 64) - return clib_error_return (0, "invalid entry"); + { + error = clib_error_return (0, "invalid entry"); + goto done; + } if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) - return clib_error_return (0, "invalid traffic class"); + { + error = clib_error_return (0, "invalid traffic class"); + goto done; + } if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS) - return clib_error_return (0, "invalid traffic class"); + { + error = clib_error_return (0, "invalid traffic class"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -911,7 +985,10 @@ set_dpdk_if_hqos_tctbl (vlib_main_t * vm, unformat_input_t * input, uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers"); /* Should never happen, shut up Coverity warning */ if (p == 0) - return clib_error_return (0, "no worker registrations?"); + { + error = clib_error_return (0, "no worker registrations?"); + goto done; + } vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0]; int worker_thread_first = tr->first_index; @@ -921,7 +998,10 @@ set_dpdk_if_hqos_tctbl (vlib_main_t * vm, unformat_input_t * input, for (i = 0; i < worker_thread_count; i++) xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val; - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -939,6 +1019,7 @@ set_dpdk_if_hqos_pktfield (vlib_main_t * vm, unformat_input_t * input, unformat_input_t _line_input, *line_input = &_line_input; vlib_thread_main_t *tm = vlib_get_thread_main (); dpdk_main_t *dm = &dpdk_main; + clib_error_t *error = NULL; /* Device specific data */ struct rte_eth_dev_info dev_info; @@ -984,15 +1065,19 @@ set_dpdk_if_hqos_pktfield (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "mask %llx", &mask)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - /* Get interface */ if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify valid interface name"); + { + error = clib_error_return (0, "please specify valid interface name"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -1019,7 +1104,7 @@ set_dpdk_if_hqos_pktfield (vlib_main_t * vm, unformat_input_t * input, if (devconf->hqos_enabled == 0) { vlib_cli_output (vm, "HQoS disabled for this interface"); - return 0; + goto done; } n_subports_per_port = devconf->hqos.port.n_subports_per_port; @@ -1028,27 +1113,39 @@ set_dpdk_if_hqos_pktfield (vlib_main_t * vm, unformat_input_t * input, /* Validate packet field configuration: id, offset and mask */ if (id >= 3) - return clib_error_return (0, "invalid packet field id"); + { + error = clib_error_return (0, "invalid packet field id"); + goto done; + } switch (id) { case 0: if (dpdk_hqos_validate_mask (mask, n_subports_per_port) != 0) - return clib_error_return (0, "invalid subport ID mask " - "(n_subports_per_port = %u)", - n_subports_per_port); + { + error = clib_error_return (0, "invalid subport ID mask " + "(n_subports_per_port = %u)", + n_subports_per_port); + goto done; + } break; case 1: if (dpdk_hqos_validate_mask (mask, n_pipes_per_subport) != 0) - return clib_error_return (0, "invalid pipe ID mask " - "(n_pipes_per_subport = %u)", - n_pipes_per_subport); + { + error = clib_error_return (0, "invalid pipe ID mask " + "(n_pipes_per_subport = %u)", + n_pipes_per_subport); + goto done; + } break; case 2: default: if (dpdk_hqos_validate_mask (mask, tctbl_size) != 0) - return clib_error_return (0, "invalid TC table index mask " - "(TC table size = %u)", tctbl_size); + { + error = clib_error_return (0, "invalid TC table index mask " + "(TC table size = %u)", tctbl_size); + goto done; + } } /* Propagate packet field configuration to all workers */ @@ -1075,7 +1172,10 @@ set_dpdk_if_hqos_pktfield (vlib_main_t * vm, unformat_input_t * input, __builtin_ctzll (mask); } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -1106,6 +1206,7 @@ show_dpdk_if_hqos (vlib_main_t * vm, unformat_input_t * input, dpdk_device_config_t *devconf = 0; vlib_thread_registration_t *tr; uword *p = 0; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -1117,14 +1218,18 @@ show_dpdk_if_hqos (vlib_main_t * vm, unformat_input_t * input, &hw_if_index)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify interface name!!"); + { + error = clib_error_return (0, "please specify interface name!!"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -1151,7 +1256,7 @@ show_dpdk_if_hqos (vlib_main_t * vm, unformat_input_t * input, if (devconf->hqos_enabled == 0) { vlib_cli_output (vm, "HQoS disabled for this interface"); - return 0; + goto done; } /* Detect the set of worker threads */ @@ -1159,7 +1264,10 @@ show_dpdk_if_hqos (vlib_main_t * vm, unformat_input_t * input, /* Should never happen, shut up Coverity warning */ if (p == 0) - return clib_error_return (0, "no worker registrations?"); + { + error = clib_error_return (0, "no worker registrations?"); + goto done; + } tr = (vlib_thread_registration_t *) p[0]; @@ -1284,7 +1392,10 @@ show_dpdk_if_hqos (vlib_main_t * vm, unformat_input_t * input, } #endif - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -1315,6 +1426,7 @@ show_dpdk_hqos_queue_stats (vlib_main_t * vm, unformat_input_t * input, u32 qindex; struct rte_sched_queue_stats stats; u16 qlen; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -1339,14 +1451,18 @@ show_dpdk_hqos_queue_stats (vlib_main_t * vm, unformat_input_t * input, ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "please specify interface name!!"); + { + error = clib_error_return (0, "please specify interface name!!"); + goto done; + } hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index); xd = vec_elt_at_index (dm->devices, hw->dev_instance); @@ -1373,7 +1489,7 @@ show_dpdk_hqos_queue_stats (vlib_main_t * vm, unformat_input_t * input, if (devconf->hqos_enabled == 0) { vlib_cli_output (vm, "HQoS disabled for this interface"); - return 0; + goto done; } /* @@ -1386,7 +1502,10 @@ show_dpdk_hqos_queue_stats (vlib_main_t * vm, unformat_input_t * input, if (rte_sched_queue_read_stats (xd->hqos_ht->hqos, qindex, &stats, &qlen) != 0) - return clib_error_return (0, "failed to read stats"); + { + error = clib_error_return (0, "failed to read stats"); + goto done; + } vlib_cli_output (vm, "%=24s%=16s", "Stats Parameter", "Value"); vlib_cli_output (vm, "%=24s%=16d", "Packets", stats.n_pkts); @@ -1399,7 +1518,10 @@ show_dpdk_hqos_queue_stats (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "%=24s%=16d", "Bytes dropped", stats.n_bytes_dropped); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/devices/dpdk/ipsec/cli.c b/src/vnet/devices/dpdk/ipsec/cli.c index 93df4a64..f9d3a5d0 100644 --- a/src/vnet/devices/dpdk/ipsec/cli.c +++ b/src/vnet/devices/dpdk/ipsec/cli.c @@ -111,6 +111,7 @@ lcore_cryptodev_map_fn (vlib_main_t * vm, unformat_input_t * input, { unformat_input_t _line_input, *line_input = &_line_input; u16 detail = 0; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -120,15 +121,19 @@ lcore_cryptodev_map_fn (vlib_main_t * vm, unformat_input_t * input, if (unformat (line_input, "verbose")) detail = 1; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - dpdk_ipsec_show_mapping (vm, detail); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/devices/netmap/cli.c b/src/vnet/devices/netmap/cli.c index 6157f27c..71363294 100644 --- a/src/vnet/devices/netmap/cli.c +++ b/src/vnet/devices/netmap/cli.c @@ -37,6 +37,7 @@ netmap_create_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 is_pipe = 0; u8 is_master = 0; u32 sw_if_index = ~0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -57,30 +58,48 @@ netmap_create_command_fn (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "slave")) is_master = 0; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (host_if_name == NULL) - return clib_error_return (0, "missing host interface name"); + { + error = clib_error_return (0, "missing host interface name"); + goto done; + } r = netmap_create_if (vm, host_if_name, hw_addr_ptr, is_pipe, is_master, &sw_if_index); if (r == VNET_API_ERROR_SYSCALL_ERROR_1) - return clib_error_return (0, "%s (errno %d)", strerror (errno), errno); + { + error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno); + goto done; + } if (r == VNET_API_ERROR_INVALID_INTERFACE) - return clib_error_return (0, "Invalid interface name"); + { + error = clib_error_return (0, "Invalid interface name"); + goto done; + } if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS) - return clib_error_return (0, "Interface already exists"); + { + error = clib_error_return (0, "Interface already exists"); + goto done; + } vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index); - return 0; + +done: + unformat_free (line_input); + + return error; } /*? @@ -144,6 +163,7 @@ netmap_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, { unformat_input_t _line_input, *line_input = &_line_input; u8 *host_if_name = NULL; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -154,17 +174,25 @@ netmap_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, if (unformat (line_input, "name %s", &host_if_name)) ; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (host_if_name == NULL) - return clib_error_return (0, "missing host interface name"); + { + error = clib_error_return (0, "missing host interface name"); + goto done; + } netmap_delete_if (vm, host_if_name); - return 0; +done: + unformat_free (line_input); + + return error; } /*? diff --git a/src/vnet/devices/virtio/vhost-user.c b/src/vnet/devices/virtio/vhost-user.c index 315daa77..c43f6e67 100644 --- a/src/vnet/devices/virtio/vhost-user.c +++ b/src/vnet/devices/virtio/vhost-user.c @@ -2682,6 +2682,7 @@ vhost_user_connect_command_fn (vlib_main_t * vm, u32 custom_dev_instance = ~0; u8 hwaddr[6]; u8 *hw = NULL; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2704,10 +2705,12 @@ vhost_user_connect_command_fn (vlib_main_t * vm, renumber = 1; } else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); vnet_main_t *vnm = vnet_get_main (); @@ -2716,14 +2719,18 @@ vhost_user_connect_command_fn (vlib_main_t * vm, is_server, &sw_if_index, feature_mask, renumber, custom_dev_instance, hw))) { - vec_free (sock_filename); - return clib_error_return (0, "vhost_user_create_if returned %d", rv); + error = clib_error_return (0, "vhost_user_create_if returned %d", rv); + goto done; } - vec_free (sock_filename); vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index); - return 0; + +done: + vec_free (sock_filename); + unformat_free (line_input); + + return error; } clib_error_t * @@ -2734,6 +2741,7 @@ vhost_user_delete_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u32 sw_if_index = ~0; vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2751,15 +2759,25 @@ vhost_user_delete_command_fn (vlib_main_t * vm, vnet_get_sup_hw_interface (vnm, sw_if_index); if (hwif == NULL || vhost_user_dev_class.index != hwif->dev_class_index) - return clib_error_return (0, "Not a vhost interface"); + { + error = clib_error_return (0, "Not a vhost interface"); + goto done; + } } else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); + vhost_user_delete_if (vnm, vm, sw_if_index); - return 0; + +done: + unformat_free (line_input); + + return error; } int @@ -3286,6 +3304,7 @@ vhost_thread_command_fn (vlib_main_t * vm, u32 sw_if_index; u8 del = 0; int rv; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -3295,9 +3314,9 @@ vhost_thread_command_fn (vlib_main_t * vm, (line_input, "%U %d", unformat_vnet_sw_interface, vnet_get_main (), &sw_if_index, &worker_thread_index)) { - unformat_free (line_input); - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; } if (unformat (line_input, "del")) @@ -3305,9 +3324,16 @@ vhost_thread_command_fn (vlib_main_t * vm, if ((rv = vhost_user_thread_placement (sw_if_index, worker_thread_index, del))) - return clib_error_return (0, "vhost_user_thread_placement returned %d", - rv); - return 0; + { + error = clib_error_return (0, "vhost_user_thread_placement returned %d", + rv); + goto done; + } + +done: + unformat_free (line_input); + + return error; } diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index d624587d..d4476ac4 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -491,6 +491,7 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, u32 num_m_args = 0; u8 is_add = 1; u32 sw_if_index; + clib_error_t *error = NULL; /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -508,16 +509,24 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "teb")) teb = 1; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args < 2) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } if (memcmp (&src, &dst, sizeof(src)) == 0) - return clib_error_return (0, "src and dst are identical"); + { + error = clib_error_return (0, "src and dst are identical"); + goto done; + } memset (a, 0, sizeof (*a)); a->outer_fib_id = outer_fib_id; @@ -536,15 +545,21 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index); break; case VNET_API_ERROR_INVALID_VALUE: - return clib_error_return (0, "GRE tunnel already exists..."); + error = clib_error_return (0, "GRE tunnel already exists..."); + goto done; case VNET_API_ERROR_NO_SUCH_FIB: - return clib_error_return (0, "outer fib ID %d doesn't exist\n", - outer_fib_id); + error = clib_error_return (0, "outer fib ID %d doesn't exist\n", + outer_fib_id); + goto done; default: - return clib_error_return (0, "vnet_gre_add_del_tunnel returned %d", rv); + error = clib_error_return (0, "vnet_gre_add_del_tunnel returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (create_gre_tunnel_command, static) = { diff --git a/src/vnet/ip/ip4_source_check.c b/src/vnet/ip/ip4_source_check.c index d461cc88..3af32f2e 100644 --- a/src/vnet/ip/ip4_source_check.c +++ b/src/vnet/ip/ip4_source_check.c @@ -399,6 +399,8 @@ set_ip_source_check (vlib_main_t * vm, vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, is_del == 0, &config, sizeof (config)); done: + unformat_free (line_input); + return error; } @@ -531,7 +533,9 @@ ip_source_check_accept (vlib_main_t * vm, } done: - return (error); + unformat_free (line_input); + + return error; } /*? diff --git a/src/vnet/ip/ip4_test.c b/src/vnet/ip/ip4_test.c index 45d17113..73dabfdc 100644 --- a/src/vnet/ip/ip4_test.c +++ b/src/vnet/ip/ip4_test.c @@ -143,8 +143,11 @@ thrash (vlib_main_t * vm, else if (unformat (line_input, "verbose")) verbose = 1; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } } @@ -178,7 +181,7 @@ thrash (vlib_main_t * vm, if (p == 0) { vlib_cli_output (vm, "Couldn't map fib id %d to fib index\n", table_id); - return 0; + goto done; } table_index = p[0]; @@ -294,7 +297,11 @@ thrash (vlib_main_t * vm, pool_free (tm->route_pool); } - return 0; + +done: + unformat_free (line_input); + + return error; } /*? diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 7229591e..6b53137f 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -2923,7 +2923,10 @@ ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, else if (unformat (line_input, "ra-lifetime")) { if (!unformat (line_input, "%d", &ra_lifetime)) - return (error = unformat_parse_error (line_input)); + { + error = unformat_parse_error (line_input); + goto done; + } use_lifetime = 1; break; } @@ -2931,13 +2934,19 @@ ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, { if (!unformat (line_input, "%d %d", &ra_initial_count, &ra_initial_interval)) - return (error = unformat_parse_error (line_input)); + { + error = unformat_parse_error (line_input); + goto done; + } break; } else if (unformat (line_input, "ra-interval")) { if (!unformat (line_input, "%d", &ra_max_interval)) - return (error = unformat_parse_error (line_input)); + { + error = unformat_parse_error (line_input); + goto done; + } if (!unformat (line_input, "%d", &ra_min_interval)) ra_min_interval = 0; @@ -2949,7 +2958,10 @@ ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, break; } else - return (unformat_parse_error (line_input)); + { + error = unformat_parse_error (line_input); + goto done; + } } if (add_radv_info) @@ -3006,7 +3018,10 @@ ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, else if (unformat (line_input, "no-onlink")) no_onlink = 1; else - return (unformat_parse_error (line_input)); + { + error = unformat_parse_error (line_input); + goto done; + } } ip6_neighbor_ra_prefix (vm, sw_if_index, @@ -3018,9 +3033,9 @@ ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, off_link, no_autoconfig, no_onlink, is_no); } +done: unformat_free (line_input); -done: return error; } diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index 0ef0e7a6..807b87b6 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -568,8 +568,6 @@ vnet_ip_route_cmd (vlib_main_t * vm, } } - unformat_free (line_input); - if (vec_len (prefixs) == 0) { error = @@ -704,6 +702,7 @@ done: vec_free (dpos); vec_free (prefixs); vec_free (rpaths); + unformat_free (line_input); return error; } @@ -872,8 +871,6 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, } } - unformat_free (line_input); - if (~0 == table_id) { /* @@ -970,6 +967,8 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, (scount * gcount) / (timet[1] - timet[0])); done: + unformat_free (line_input); + return error; } @@ -1149,24 +1148,37 @@ probe_neighbor_address (vlib_main_t * vm, is_ip4 = 0; } else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (sw_if_index == ~0) - return clib_error_return (0, "Interface required, not set."); + { + error = clib_error_return (0, "Interface required, not set."); + goto done; + } if (address_set == 0) - return clib_error_return (0, "ip address required, not set."); + { + error = clib_error_return (0, "ip address required, not set."); + goto done; + } if (address_set > 1) - return clib_error_return (0, "Multiple ip addresses not supported."); + { + error = clib_error_return (0, "Multiple ip addresses not supported."); + goto done; + } if (is_ip4) error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count); else error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count); +done: + unformat_free (line_input); + return error; } diff --git a/src/vnet/ipsec-gre/interface.c b/src/vnet/ipsec-gre/interface.c index 3b6e4ac2..0772ce73 100644 --- a/src/vnet/ipsec-gre/interface.c +++ b/src/vnet/ipsec-gre/interface.c @@ -232,6 +232,7 @@ create_ipsec_gre_tunnel_command_fn (vlib_main_t * vm, vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a; int rv; u32 sw_if_index; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -250,16 +251,24 @@ create_ipsec_gre_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "remote-sa %d", &rsa)) num_m_args++; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args < 4) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } if (memcmp (&src, &dst, sizeof (src)) == 0) - return clib_error_return (0, "src and dst are identical"); + { + error = clib_error_return (0, "src and dst are identical"); + goto done; + } memset (a, 0, sizeof (*a)); a->is_add = is_add; @@ -277,14 +286,19 @@ create_ipsec_gre_tunnel_command_fn (vlib_main_t * vm, vnet_get_main (), sw_if_index); break; case VNET_API_ERROR_INVALID_VALUE: - return clib_error_return (0, "GRE tunnel already exists..."); + error = clib_error_return (0, "GRE tunnel already exists..."); + goto done; default: - return clib_error_return (0, - "vnet_ipsec_gre_add_del_tunnel returned %d", - rv); + error = clib_error_return (0, + "vnet_ipsec_gre_add_del_tunnel returned %d", + rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c index 3c1e26f2..0e034402 100644 --- a/src/vnet/ipsec/ipsec_cli.c +++ b/src/vnet/ipsec/ipsec_cli.c @@ -32,6 +32,7 @@ set_interface_spd_command_fn (vlib_main_t * vm, u32 sw_if_index = (u32) ~ 0; u32 spd_id; int is_add = 1; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -43,14 +44,18 @@ set_interface_spd_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) is_add = 0; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - - unformat_free (line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -72,7 +77,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, ipsec_sa_t sa; int is_add = ~0; u8 *ck = 0, *ik = 0; - clib_error_t *err = 0; + clib_error_t *error = NULL; memset (&sa, 0, sizeof (sa)); @@ -90,8 +95,11 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "esp")) sa.protocol = IPSEC_PROTOCOL_ESP; else if (unformat (line_input, "ah")) - //sa.protocol = IPSEC_PROTOCOL_AH; - return clib_error_return (0, "unsupported security protocol 'AH'"); + { + //sa.protocol = IPSEC_PROTOCOL_AH; + error = clib_error_return (0, "unsupported security protocol 'AH'"); + goto done; + } else if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck)) sa.crypto_key_len = vec_len (ck); @@ -102,8 +110,12 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, { if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 || sa.crypto_alg >= IPSEC_CRYPTO_N_ALG) - return clib_error_return (0, "unsupported crypto-alg: '%U'", - format_ipsec_crypto_alg, sa.crypto_alg); + { + error = clib_error_return (0, "unsupported crypto-alg: '%U'", + format_ipsec_crypto_alg, + sa.crypto_alg); + goto done; + } } else if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik)) @@ -113,8 +125,12 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, { if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 || sa.integ_alg >= IPSEC_INTEG_N_ALG) - return clib_error_return (0, "unsupported integ-alg: '%U'", - format_ipsec_integ_alg, sa.integ_alg); + { + error = clib_error_return (0, "unsupported integ-alg: '%U'", + format_ipsec_integ_alg, + sa.integ_alg); + goto done; + } } else if (unformat (line_input, "tunnel-src %U", unformat_ip4_address, &sa.tunnel_src_addr.ip4)) @@ -135,12 +151,13 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, sa.is_tunnel_ip6 = 1; } else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (sa.crypto_key_len > sizeof (sa.crypto_key)) sa.crypto_key_len = sizeof (sa.crypto_key); @@ -156,14 +173,17 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, if (is_add) { ASSERT (im->cb.check_support_cb); - err = im->cb.check_support_cb (&sa); - if (err) - return err; + error = im->cb.check_support_cb (&sa); + if (error) + goto done; } ipsec_add_del_sa (vm, &sa, is_add); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -183,6 +203,7 @@ ipsec_spd_add_del_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u32 spd_id = ~0; int is_add = ~0; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -196,18 +217,25 @@ ipsec_spd_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "%u", &spd_id)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (spd_id == ~0) - return clib_error_return (0, "please specify SPD ID"); + { + error = clib_error_return (0, "please specify SPD ID"); + goto done; + } ipsec_add_del_spd (vm, spd_id, is_add); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -230,6 +258,7 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, int is_add = 0; int is_ip_any = 1; u32 tmp, tmp2; + clib_error_t *error = NULL; memset (&p, 0, sizeof (p)); p.lport.stop = p.rport.stop = ~0; @@ -262,7 +291,10 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, &p.policy)) { if (p.policy == IPSEC_POLICY_ACTION_RESOLVE) - return clib_error_return (0, "unsupported action: 'resolve'"); + { + error = clib_error_return (0, "unsupported action: 'resolve'"); + goto done; + } } else if (unformat (line_input, "sa %u", &p.sa_id)) ; @@ -300,19 +332,24 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, p.rport.stop = tmp2; } else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - ipsec_add_del_policy (vm, &p, is_add); if (is_ip_any) { p.is_ipv6 = 1; ipsec_add_del_policy (vm, &p, is_add); } - return 0; + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -332,6 +369,7 @@ set_ipsec_sa_key_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; ipsec_sa_t sa; u8 *ck = 0, *ik = 0; + clib_error_t *error = NULL; memset (&sa, 0, sizeof (sa)); @@ -349,12 +387,13 @@ set_ipsec_sa_key_command_fn (vlib_main_t * vm, if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik)) sa.integ_key_len = vec_len (ik); else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (sa.crypto_key_len > sizeof (sa.crypto_key)) sa.crypto_key_len = sizeof (sa.crypto_key); @@ -369,7 +408,10 @@ set_ipsec_sa_key_command_fn (vlib_main_t * vm, ipsec_set_sa_key (vm, &sa); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -649,6 +691,7 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm, ipsec_add_del_tunnel_args_t a; int rv; u32 num_m_args = 0; + clib_error_t *error = NULL; memset (&a, 0, sizeof (a)); a.is_add = 1; @@ -673,13 +716,18 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "del")) a.is_add = 0; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args < 4) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } rv = ipsec_add_del_tunnel_if (&a); @@ -689,16 +737,21 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm, break; case VNET_API_ERROR_INVALID_VALUE: if (a.is_add) - return clib_error_return (0, - "IPSec tunnel interface already exists..."); + error = clib_error_return (0, + "IPSec tunnel interface already exists..."); else - return clib_error_return (0, "IPSec tunnel interface not exists..."); + error = clib_error_return (0, "IPSec tunnel interface not exists..."); + goto done; default: - return clib_error_return (0, "ipsec_register_interface returned %d", - rv); + error = clib_error_return (0, "ipsec_register_interface returned %d", + rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -720,6 +773,7 @@ set_interface_key_command_fn (vlib_main_t * vm, u32 hw_if_index = (u32) ~ 0; u32 alg; u8 *key = 0; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -748,25 +802,38 @@ set_interface_key_command_fn (vlib_main_t * vm, else if (unformat (line_input, "%U", unformat_hex_string, &key)) ; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (type == IPSEC_IF_SET_KEY_TYPE_NONE) - return clib_error_return (0, "unknown key type"); + { + error = clib_error_return (0, "unknown key type"); + goto done; + } if (alg > 0 && vec_len (key) == 0) - return clib_error_return (0, "key is not specified"); + { + error = clib_error_return (0, "key is not specified"); + goto done; + } if (hw_if_index == (u32) ~ 0) - return clib_error_return (0, "interface not specified"); + { + error = clib_error_return (0, "interface not specified"); + goto done; + } ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key); + +done: vec_free (key); + unformat_free (line_input); - return 0; + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/l2/l2_patch.c b/src/vnet/l2/l2_patch.c index 5e4691f4..ff3d2f3a 100644 --- a/src/vnet/l2/l2_patch.c +++ b/src/vnet/l2/l2_patch.c @@ -315,6 +315,7 @@ test_patch_command_fn (vlib_main_t * vm, int rx_set = 0; int tx_set = 0; int is_add = 1; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -335,10 +336,16 @@ test_patch_command_fn (vlib_main_t * vm, } if (rx_set == 0) - return clib_error_return (0, "rx interface not set"); + { + error = clib_error_return (0, "rx interface not set"); + goto done; + } if (tx_set == 0) - return clib_error_return (0, "tx interface not set"); + { + error = clib_error_return (0, "tx interface not set"); + goto done; + } rv = vnet_l2_patch_add_del (rx_sw_if_index, tx_sw_if_index, is_add); @@ -348,17 +355,24 @@ test_patch_command_fn (vlib_main_t * vm, break; case VNET_API_ERROR_INVALID_SW_IF_INDEX: - return clib_error_return (0, "rx interface not a physical port"); + error = clib_error_return (0, "rx interface not a physical port"); + goto done; case VNET_API_ERROR_INVALID_SW_IF_INDEX_2: - return clib_error_return (0, "tx interface not a physical port"); + error = clib_error_return (0, "tx interface not a physical port"); + goto done; default: - return clib_error_return + error = clib_error_return (0, "WARNING: vnet_l2_patch_add_del returned %d", rv); + goto done; } - return 0; + +done: + unformat_free (line_input); + + return error; } /*? diff --git a/src/vnet/l2/l2_xcrw.c b/src/vnet/l2/l2_xcrw.c index 70610a85..d08a5d8f 100644 --- a/src/vnet/l2/l2_xcrw.c +++ b/src/vnet/l2/l2_xcrw.c @@ -409,6 +409,7 @@ set_l2_xcrw_command_fn (vlib_main_t * vm, u8 *rw = 0; vnet_main_t *vnm = vnet_get_main (); int rv; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) @@ -416,8 +417,11 @@ set_l2_xcrw_command_fn (vlib_main_t * vm, if (!unformat (line_input, "%U", unformat_vnet_sw_interface, vnm, &l2_sw_if_index)) - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -436,7 +440,10 @@ set_l2_xcrw_command_fn (vlib_main_t * vm, } if (next_node_index == ~0) - return clib_error_return (0, "next node not specified"); + { + error = clib_error_return (0, "next node not specified"); + goto done; + } if (tx_fib_id != ~0) { @@ -448,7 +455,11 @@ set_l2_xcrw_command_fn (vlib_main_t * vm, p = hash_get (ip4_main.fib_index_by_table_id, tx_fib_id); if (p == 0) - return clib_error_return (0, "nonexistent tx_fib_id %d", tx_fib_id); + { + error = + clib_error_return (0, "nonexistent tx_fib_id %d", tx_fib_id); + goto done; + } tx_fib_index = p[0]; } @@ -463,16 +474,21 @@ set_l2_xcrw_command_fn (vlib_main_t * vm, break; case VNET_API_ERROR_INVALID_SW_IF_INDEX: - return clib_error_return (0, "%U not cross-connected", - format_vnet_sw_if_index_name, - vnm, l2_sw_if_index); + error = clib_error_return (0, "%U not cross-connected", + format_vnet_sw_if_index_name, + vnm, l2_sw_if_index); + goto done; + default: - return clib_error_return (0, "vnet_configure_l2_xcrw returned %d", rv); + error = clib_error_return (0, "vnet_configure_l2_xcrw returned %d", rv); + goto done; } +done: vec_free (rw); + unformat_free (line_input); - return 0; + return error; } /*? diff --git a/src/vnet/l2tp/l2tp.c b/src/vnet/l2tp/l2tp.c index a4531dab..2d323397 100644 --- a/src/vnet/l2tp/l2tp.c +++ b/src/vnet/l2tp/l2tp.c @@ -427,6 +427,7 @@ create_l2tpv3_tunnel_command_fn (vlib_main_t * vm, u32 sw_if_index; u32 encap_fib_id = ~0; u32 encap_fib_index = ~0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -455,18 +456,22 @@ create_l2tpv3_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "l2-sublayer-present")) l2_sublayer_present = 1; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (encap_fib_id != ~0) { uword *p; ip6_main_t *im = &ip6_main; if (!(p = hash_get (im->fib_index_by_table_id, encap_fib_id))) - return clib_error_return (0, "No fib with id %d", encap_fib_id); + { + error = clib_error_return (0, "No fib with id %d", encap_fib_id); + goto done; + } encap_fib_index = p[0]; } else @@ -475,9 +480,15 @@ create_l2tpv3_tunnel_command_fn (vlib_main_t * vm, } if (our_address_set == 0) - return clib_error_return (0, "our address not specified"); + { + error = clib_error_return (0, "our address not specified"); + goto done; + } if (client_address_set == 0) - return clib_error_return (0, "client address not specified"); + { + error = clib_error_return (0, "client address not specified"); + goto done; + } rv = create_l2tpv3_ipv6_tunnel (lm, &client_address, &our_address, local_session_id, remote_session_id, @@ -491,16 +502,22 @@ create_l2tpv3_tunnel_command_fn (vlib_main_t * vm, vnet_get_main (), sw_if_index); break; case VNET_API_ERROR_INVALID_VALUE: - return clib_error_return (0, "session already exists..."); + error = clib_error_return (0, "session already exists..."); + goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "session does not exist..."); + error = clib_error_return (0, "session does not exist..."); + goto done; default: - return clib_error_return (0, "l2tp_session_add_del returned %d", rv); + error = clib_error_return (0, "l2tp_session_add_del returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/lisp-cp/lisp_cli.c b/src/vnet/lisp-cp/lisp_cli.c index 25d11c61..05df9fb6 100644 --- a/src/vnet/lisp-cp/lisp_cli.c +++ b/src/vnet/lisp-cp/lisp_cli.c @@ -25,6 +25,7 @@ lisp_show_adjacencies_command_fn (vlib_main_t * vm, vlib_cli_output (vm, "%s %40s\n", "leid", "reid"); unformat_input_t _line_input, *line_input = &_line_input; u32 vni = ~0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -38,14 +39,14 @@ lisp_show_adjacencies_command_fn (vlib_main_t * vm, { vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, line_input); - return 0; + goto done; } } if (~0 == vni) { vlib_cli_output (vm, "error: no vni specified!"); - return 0; + goto done; } adjs = vnet_lisp_adjacencies_get_by_vni (vni); @@ -57,7 +58,10 @@ lisp_show_adjacencies_command_fn (vlib_main_t * vm, } vec_free (adjs); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -77,6 +81,7 @@ lisp_add_del_map_server_command_fn (vlib_main_t * vm, u8 is_add = 1, ip_set = 0; ip_address_t ip; unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -94,14 +99,14 @@ lisp_add_del_map_server_command_fn (vlib_main_t * vm, { vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, line_input); - return 0; + goto done; } } if (!ip_set) { vlib_cli_output (vm, "map-server ip address not set!"); - return 0; + goto done; } rv = vnet_lisp_add_del_map_server (&ip, is_add); @@ -109,7 +114,10 @@ lisp_add_del_map_server_command_fn (vlib_main_t * vm, vlib_cli_output (vm, "failed to %s map-server!", is_add ? "add" : "delete"); - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -191,7 +199,7 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, if (key && (0 == key_id)) { vlib_cli_output (vm, "invalid key_id!"); - return 0; + goto done;; } gid_address_copy (&a->eid, &eid); @@ -213,6 +221,8 @@ done: vec_free (locator_set_name); gid_address_free (&a->eid); vec_free (a->key); + unformat_free (line_input); + return error; } @@ -233,6 +243,7 @@ lisp_eid_table_map_command_fn (vlib_main_t * vm, u8 is_add = 1, is_l2 = 0; u32 vni = 0, dp_id = 0; unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -250,11 +261,16 @@ lisp_eid_table_map_command_fn (vlib_main_t * vm, is_l2 = 1; else { - return unformat_parse_error (line_input); + error = unformat_parse_error (line_input); + goto done; } } vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add); - return 0; + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -479,7 +495,7 @@ lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input, != ip_prefix_version (leid_ippref))) { clib_warning ("remote and local EIDs are of different types!"); - return error; + goto done; } memset (a, 0, sizeof (a[0])); @@ -512,6 +528,7 @@ lisp_map_request_mode_command_fn (vlib_main_t * vm, { unformat_input_t _i, *i = &_i; map_request_mode_t mr_mode = _MR_MODE_MAX; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, i)) @@ -533,12 +550,15 @@ lisp_map_request_mode_command_fn (vlib_main_t * vm, if (_MR_MODE_MAX == mr_mode) { clib_warning ("No LISP map request mode entered!"); - return 0; + goto done; } vnet_lisp_set_map_request_mode (mr_mode); + done: - return 0; + unformat_free (i); + + return error; } /* *INDENT-OFF* */ @@ -630,7 +650,10 @@ lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, else if (unformat (line_input, "disable")) is_add = 0; else - return clib_error_return (0, "parse error"); + { + error = clib_error_return (0, "parse error"); + goto done; + } } if (!locator_name_set) @@ -648,6 +671,8 @@ lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, done: if (locator_set_name) vec_free (locator_set_name); + unformat_free (line_input); + return error; } @@ -771,6 +796,7 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm, gid_address_t eid; u8 print_all = 1; u8 filter = 0; + clib_error_t *error = NULL; memset (&eid, 0, sizeof (eid)); @@ -787,8 +813,11 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm, else if (unformat (line_input, "remote")) filter = 2; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s", @@ -818,7 +847,7 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm, { mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid); if ((u32) ~ 0 == mi) - return 0; + goto done; mapit = pool_elt_at_index (lcm->mapping_pool, mi); locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, @@ -827,14 +856,17 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm, if (filter && !((1 == filter && ls->local) || (2 == filter && !ls->local))) { - return 0; + goto done; } vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main, lcm, mapit, ls); } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -853,6 +885,7 @@ lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, unformat_input_t _line_input, *line_input = &_line_input; u8 is_enabled = 0; u8 is_set = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -869,16 +902,24 @@ lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, is_set = 1; else { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; } } if (!is_set) - return clib_error_return (0, "state not set"); + { + error = clib_error_return (0, "state not set"); + goto done; + } vnet_lisp_enable_disable (is_enabled); - return 0; + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -897,6 +938,7 @@ lisp_map_register_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u8 is_enabled = 0; u8 is_set = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -915,18 +957,22 @@ lisp_map_register_enable_disable_command_fn (vlib_main_t * vm, { vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, line_input); - return 0; + goto done; } } if (!is_set) { vlib_cli_output (vm, "state not set!"); - return 0; + goto done; } vnet_lisp_map_register_enable_disable (is_enabled); - return 0; + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -945,6 +991,7 @@ lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u8 is_enabled = 0; u8 is_set = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -963,18 +1010,22 @@ lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm, { vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, line_input); - return 0; + goto done; } } if (!is_set) { vlib_cli_output (vm, "state not set!"); - return 0; + goto done; } vnet_lisp_rloc_probe_enable_disable (is_enabled); - return 0; + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -1022,6 +1073,7 @@ lisp_show_eid_table_map_command_fn (vlib_main_t * vm, lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); uword *vni_table = 0; u8 is_l2 = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -1040,14 +1092,17 @@ lisp_show_eid_table_map_command_fn (vlib_main_t * vm, is_l2 = 0; } else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } if (!vni_table) { vlib_cli_output (vm, "Error: expected l2|l3 param!\n"); - return 0; + goto done; } vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF"); @@ -1059,7 +1114,10 @@ lisp_show_eid_table_map_command_fn (vlib_main_t * vm, })); /* *INDENT-ON* */ - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ @@ -1131,6 +1189,8 @@ done: vec_free (locators); if (locator_set_name) vec_free (locator_set_name); + unformat_free (line_input); + return error; } @@ -1205,6 +1265,8 @@ lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm, done: vec_free (locators); vec_free (locator_set_name); + unformat_free (line_input); + return error; } @@ -1322,6 +1384,8 @@ lisp_add_del_map_resolver_command_fn (vlib_main_t * vm, } done: + unformat_free (line_input); + return error; } @@ -1372,11 +1436,11 @@ lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm, is_add ? "add" : "delete"); } +done: vec_free (locator_set_name); + unformat_free (line_input); -done: return error; - } /* *INDENT-OFF* */ @@ -1438,7 +1502,10 @@ lisp_use_petr_set_locator_set_command_fn (vlib_main_t * vm, else if (unformat (line_input, "disable")) is_add = 0; else - return clib_error_return (0, "parse error"); + { + error = clib_error_return (0, "parse error"); + goto done; + } } if (!ip_set) @@ -1454,6 +1521,8 @@ lisp_use_petr_set_locator_set_command_fn (vlib_main_t * vm, } done: + unformat_free (line_input); + return error; } diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index 2142e095..19ac22e7 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -794,6 +794,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, u32 table_id, vni, bd_id; u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0; u8 nsh_iface = 0; + clib_error_t *error = NULL; if (vnet_lisp_gpe_enable_disable_status () == 0) { @@ -828,8 +829,9 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, } else { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; } } @@ -839,7 +841,8 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main)) { - return clib_error_return (0, "NSH interface not created"); + error = clib_error_return (0, "NSH interface not created"); + goto done; } } else @@ -850,21 +853,34 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, } if (vrf_is_set && bd_index_is_set) - return clib_error_return (0, - "Cannot set both vrf and brdige domain index!"); + { + error = clib_error_return + (0, "Cannot set both vrf and brdige domain index!"); + goto done; + } if (!vni_is_set) - return clib_error_return (0, "vni must be set!"); + { + error = clib_error_return (0, "vni must be set!"); + goto done; + } if (!vrf_is_set && !bd_index_is_set) - return clib_error_return (0, "vrf or bridge domain index must be set!"); + { + error = + clib_error_return (0, "vrf or bridge domain index must be set!"); + goto done; + } if (bd_index_is_set) { if (is_add) { if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, bd_id)) - return clib_error_return (0, "L2 interface not created"); + { + error = clib_error_return (0, "L2 interface not created"); + goto done; + } } else lisp_gpe_tenant_l2_iface_unlock (vni); @@ -874,13 +890,35 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, if (is_add) { if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id)) - return clib_error_return (0, "L3 interface not created"); + { + error = clib_error_return (0, "L3 interface not created"); + goto done; + } } else lisp_gpe_tenant_l3_iface_unlock (vni); } - return (NULL); + if (nsh_iface) + { + if (is_add) + { + if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main)) + { + error = clib_error_return (0, "NSH interface not created"); + goto done; + } + else + { + lisp_gpe_del_nsh_iface (&lisp_gpe_main); + } + } + } + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c index 1f8afdae..f2fbcbd5 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.c +++ b/src/vnet/lisp-gpe/lisp_gpe.c @@ -218,6 +218,7 @@ lisp_gpe_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u8 is_en = 1; vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -231,12 +232,18 @@ lisp_gpe_enable_disable_command_fn (vlib_main_t * vm, is_en = 0; else { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; } } a->is_en = is_en; - return vnet_lisp_gpe_enable_disable (a); + error = vnet_lisp_gpe_enable_disable (a); + +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/map/map.c b/src/vnet/map/map.c index aeec6a94..a2d28118 100644 --- a/src/vnet/map/map.c +++ b/src/vnet/map/map.c @@ -465,6 +465,8 @@ map_security_check_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; + clib_error_t *error = NULL; + /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -476,11 +478,17 @@ map_security_check_command_fn (vlib_main_t * vm, else if (unformat (line_input, "on")) mm->sec_check = true; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + + return error; } static clib_error_t * @@ -490,6 +498,8 @@ map_security_check_frag_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; + clib_error_t *error = NULL; + /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -501,11 +511,17 @@ map_security_check_frag_command_fn (vlib_main_t * vm, else if (unformat (line_input, "on")) mm->sec_check_frag = true; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + + return error; } static clib_error_t * @@ -523,6 +539,7 @@ map_add_domain_command_fn (vlib_main_t * vm, u32 mtu = 0; u8 flags = 0; ip6_src_len = 128; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -559,20 +576,28 @@ map_add_domain_command_fn (vlib_main_t * vm, else if (unformat (line_input, "map-t")) flags |= MAP_DOMAIN_TRANSLATION; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args < 3) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } map_create_domain (&ip4_prefix, ip4_prefix_len, &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len, ea_bits_len, psid_offset, psid_length, &map_domain_index, mtu, flags); - return 0; +done: + unformat_free (line_input); + + return error; } static clib_error_t * @@ -582,6 +607,7 @@ map_del_domain_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; u32 num_m_args = 0; u32 map_domain_index; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -592,17 +618,25 @@ map_del_domain_command_fn (vlib_main_t * vm, if (unformat (line_input, "index %d", &map_domain_index)) num_m_args++; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args != 1) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } map_delete_domain (map_domain_index); - return 0; +done: + unformat_free (line_input); + + return error; } static clib_error_t * @@ -613,6 +647,7 @@ map_add_rule_command_fn (vlib_main_t * vm, ip6_address_t tep; u32 num_m_args = 0; u32 psid = 0, map_domain_index; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -628,19 +663,29 @@ map_add_rule_command_fn (vlib_main_t * vm, if (unformat (line_input, "ip6-dst %U", unformat_ip6_address, &tep)) num_m_args++; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args != 3) - return clib_error_return (0, "mandatory argument(s) missing"); + { + error = clib_error_return (0, "mandatory argument(s) missing"); + goto done; + } if (map_add_del_psid (map_domain_index, psid, &tep, 1) != 0) { - return clib_error_return (0, "Failing to add Mapping Rule"); + error = clib_error_return (0, "Failing to add Mapping Rule"); + goto done; } - return 0; + +done: + unformat_free (line_input); + + return error; } #if MAP_SKIP_IP6_LOOKUP @@ -653,6 +698,7 @@ map_pre_resolve_command_fn (vlib_main_t * vm, ip4_address_t ip4nh; ip6_address_t ip6nh; map_main_t *mm = &map_main; + clib_error_t *error = NULL; memset (&ip4nh, 0, sizeof (ip4nh)); memset (&ip6nh, 0, sizeof (ip6nh)); @@ -669,14 +715,19 @@ map_pre_resolve_command_fn (vlib_main_t * vm, if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh)) mm->preresolve_ip6 = ip6nh; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); map_pre_resolve (&ip4nh, &ip6nh); - return 0; +done: + unformat_free (line_input); + + return error; } #endif @@ -688,6 +739,7 @@ map_icmp_relay_source_address_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; ip4_address_t icmp_src_address; map_main_t *mm = &map_main; + clib_error_t *error = NULL; mm->icmp4_src_address.as_u32 = 0; @@ -701,12 +753,17 @@ map_icmp_relay_source_address_command_fn (vlib_main_t * vm, (line_input, "%U", unformat_ip4_address, &icmp_src_address)) mm->icmp4_src_address = icmp_src_address; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + return error; } static clib_error_t * @@ -717,6 +774,7 @@ map_icmp_unreachables_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; int num_m_args = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -730,16 +788,21 @@ map_icmp_unreachables_command_fn (vlib_main_t * vm, else if (unformat (line_input, "off")) mm->icmp6_enabled = false; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (num_m_args != 1) - return clib_error_return (0, "mandatory argument(s) missing"); + error = clib_error_return (0, "mandatory argument(s) missing"); - return 0; +done: + unformat_free (line_input); + + return error; } static clib_error_t * @@ -748,6 +811,7 @@ map_fragment_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -760,12 +824,17 @@ map_fragment_command_fn (vlib_main_t * vm, else if (unformat (line_input, "outer")) mm->frag_inner = false; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + return error; } static clib_error_t * @@ -775,6 +844,7 @@ map_fragment_df_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -787,12 +857,17 @@ map_fragment_df_command_fn (vlib_main_t * vm, else if (unformat (line_input, "off")) mm->frag_ignore_df = false; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + return error; } static clib_error_t * @@ -803,6 +878,7 @@ map_traffic_class_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; map_main_t *mm = &map_main; u32 tc = 0; + clib_error_t *error = NULL; mm->tc_copy = false; @@ -817,12 +893,17 @@ map_traffic_class_command_fn (vlib_main_t * vm, else if (unformat (line_input, "%x", &tc)) mm->tc = tc & 0xff; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + +done: unformat_free (line_input); - return 0; + return error; } static u8 * @@ -922,6 +1003,7 @@ show_map_domain_command_fn (vlib_main_t * vm, unformat_input_t * input, map_domain_t *d; bool counters = false; u32 map_domain_index = ~0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -934,10 +1016,12 @@ show_map_domain_command_fn (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "index %d", &map_domain_index)) ; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); if (pool_elts (mm->domains) == 0) vlib_cli_output (vm, "No MAP domains are configured..."); @@ -952,15 +1036,19 @@ show_map_domain_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (pool_is_free_index (mm->domains, map_domain_index)) { - return clib_error_return (0, "MAP domain does not exists %d", - map_domain_index); + error = clib_error_return (0, "MAP domain does not exists %d", + map_domain_index); + goto done; } d = pool_elt_at_index (mm->domains, map_domain_index); vlib_cli_output (vm, "%U", format_map_domain, d, counters); } - return 0; +done: + unformat_free (line_input); + + return error; } static clib_error_t * diff --git a/src/vnet/mpls/mpls.c b/src/vnet/mpls/mpls.c index 0e610e17..7ae4aa00 100644 --- a/src/vnet/mpls/mpls.c +++ b/src/vnet/mpls/mpls.c @@ -470,6 +470,8 @@ vnet_mpls_local_label (vlib_main_t * vm, } done: + unformat_free (line_input); + return error; } diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c index 8d1e30a3..e488271d 100644 --- a/src/vnet/mpls/mpls_tunnel.c +++ b/src/vnet/mpls/mpls_tunnel.c @@ -535,6 +535,7 @@ vnet_create_mpls_tunnel_command_fn (vlib_main_t * vm, fib_route_path_t rpath, *rpaths = NULL; mpls_label_t out_label = MPLS_LABEL_INVALID, *labels = NULL; u32 sw_if_index; + clib_error_t *error = NULL; memset(&rpath, 0, sizeof(rpath)); @@ -595,8 +596,11 @@ vnet_create_mpls_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "l2-only")) l2_only = 1; else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } } if (is_del) @@ -606,17 +610,22 @@ vnet_create_mpls_tunnel_command_fn (vlib_main_t * vm, else { if (0 == vec_len(labels)) - return clib_error_return (0, "No Output Labels '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "No Output Labels '%U'", + format_unformat_error, line_input); + goto done; + } vec_add1(rpaths, rpath); vnet_mpls_tunnel_add(rpaths, labels, l2_only, &sw_if_index); } +done: vec_free(labels); vec_free(rpaths); + unformat_free (line_input); - return (NULL); + return error; } /*? diff --git a/src/vnet/pg/cli.c b/src/vnet/pg/cli.c index f5896b43..3c249a7b 100644 --- a/src/vnet/pg/cli.c +++ b/src/vnet/pg/cli.c @@ -547,21 +547,30 @@ pg_capture_cmd_fn (vlib_main_t * vm, else { error = clib_error_create ("unknown input `%U'", - format_unformat_error, input); - return error; + format_unformat_error, line_input); + goto done; } } if (!hi) - return clib_error_return (0, "Please specify interface name"); + { + error = clib_error_return (0, "Please specify interface name"); + goto done; + } if (hi->dev_class_index != pg_dev_class.index) - return clib_error_return (0, "Please specify packet-generator interface"); + { + error = + clib_error_return (0, "Please specify packet-generator interface"); + goto done; + } if (!pcap_file_name && is_disable == 0) - return clib_error_return (0, "Please specify pcap file name"); + { + error = clib_error_return (0, "Please specify pcap file name"); + goto done; + } - unformat_free (line_input); pg_capture_args_t _a, *a = &_a; @@ -572,6 +581,10 @@ pg_capture_cmd_fn (vlib_main_t * vm, a->count = count; error = pg_capture (a); + +done: + unformat_free (line_input); + return error; } @@ -590,6 +603,7 @@ create_pg_if_cmd_fn (vlib_main_t * vm, pg_main_t *pg = &pg_main; unformat_input_t _line_input, *line_input = &_line_input; u32 if_id; + clib_error_t *error = NULL; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -600,14 +614,19 @@ create_pg_if_cmd_fn (vlib_main_t * vm, ; else - return clib_error_create ("unknown input `%U'", - format_unformat_error, input); + { + error = clib_error_create ("unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + pg_interface_add_or_get (pg, if_id); + +done: unformat_free (line_input); - pg_interface_add_or_get (pg, if_id); - return 0; + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/policer/node_funcs.c b/src/vnet/policer/node_funcs.c index 1f4997ff..457dd09f 100644 --- a/src/vnet/policer/node_funcs.c +++ b/src/vnet/policer/node_funcs.c @@ -447,6 +447,7 @@ test_policer_command_fn (vlib_main_t * vm, int rx_set = 0; int is_add = 1; int is_show = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -468,7 +469,10 @@ test_policer_command_fn (vlib_main_t * vm, } if (rx_set == 0) - return clib_error_return (0, "interface not set"); + { + error = clib_error_return (0, "interface not set"); + goto done; + } if (is_show) { @@ -477,12 +481,13 @@ test_policer_command_fn (vlib_main_t * vm, policer = pool_elt_at_index (pm->policers, pi); vlib_cli_output (vm, "%U", format_policer_instance, policer); - return 0; + goto done; } if (is_add && config_name == 0) { - return clib_error_return (0, "policer config name required"); + error = clib_error_return (0, "policer config name required"); + goto done; } rv = test_policer_add_del (rx_sw_if_index, config_name, is_add); @@ -493,11 +498,15 @@ test_policer_command_fn (vlib_main_t * vm, break; default: - return clib_error_return + error = clib_error_return (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/policer/policer.c b/src/vnet/policer/policer.c index 290a6af5..cd754e29 100644 --- a/src/vnet/policer/policer.c +++ b/src/vnet/policer/policer.c @@ -413,6 +413,7 @@ configure_policer_command_fn (vlib_main_t * vm, u8 is_add = 1; u8 *name = 0; u32 pi; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -433,13 +434,19 @@ configure_policer_command_fn (vlib_main_t * vm, foreach_config_param #undef _ else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } + error = policer_add_del (vm, name, &c, &pi, is_add); + +done: unformat_free (line_input); - return policer_add_del (vm, name, &c, &pi, is_add); + return error; } /* *INDENT-OFF* */ diff --git a/src/vnet/unix/tapcli.c b/src/vnet/unix/tapcli.c index 48e81b50..25c930c6 100644 --- a/src/vnet/unix/tapcli.c +++ b/src/vnet/unix/tapcli.c @@ -1308,6 +1308,7 @@ tap_connect_command_fn (vlib_main_t * vm, int ip6_address_set = 0; u32 ip4_mask_width = 0; u32 ip6_mask_width = 0; + clib_error_t *error = NULL; if (tm->is_disabled) return clib_error_return (0, "device disabled..."); @@ -1336,12 +1337,18 @@ tap_connect_command_fn (vlib_main_t * vm, else if (unformat (line_input, "%s", &intfc_name)) ; else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } } if (intfc_name == 0) - return clib_error_return (0, "interface name must be specified"); + { + error = clib_error_return (0, "interface name must be specified"); + goto done; + } memset (ap, 0, sizeof (*ap)); @@ -1367,48 +1374,64 @@ tap_connect_command_fn (vlib_main_t * vm, switch (rv) { case VNET_API_ERROR_SYSCALL_ERROR_1: - return clib_error_return (0, "Couldn't open /dev/net/tun"); + error = clib_error_return (0, "Couldn't open /dev/net/tun"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_2: - return clib_error_return (0, "Error setting flags on '%s'", intfc_name); - + error = clib_error_return (0, "Error setting flags on '%s'", intfc_name); + goto done; + case VNET_API_ERROR_SYSCALL_ERROR_3: - return clib_error_return (0, "Couldn't open provisioning socket"); + error = clib_error_return (0, "Couldn't open provisioning socket"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_4: - return clib_error_return (0, "Couldn't get if_index"); + error = clib_error_return (0, "Couldn't get if_index"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_5: - return clib_error_return (0, "Couldn't bind provisioning socket"); + error = clib_error_return (0, "Couldn't bind provisioning socket"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_6: - return clib_error_return (0, "Couldn't set device non-blocking flag"); + error = clib_error_return (0, "Couldn't set device non-blocking flag"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_7: - return clib_error_return (0, "Couldn't set device MTU"); + error = clib_error_return (0, "Couldn't set device MTU"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_8: - return clib_error_return (0, "Couldn't get interface flags"); + error = clib_error_return (0, "Couldn't get interface flags"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_9: - return clib_error_return (0, "Couldn't set intfc admin state up"); + error = clib_error_return (0, "Couldn't set intfc admin state up"); + goto done; case VNET_API_ERROR_SYSCALL_ERROR_10: - return clib_error_return (0, "Couldn't set intfc address/mask"); + error = clib_error_return (0, "Couldn't set intfc address/mask"); + goto done; case VNET_API_ERROR_INVALID_REGISTRATION: - return clib_error_return (0, "Invalid registration"); + error = clib_error_return (0, "Invalid registration"); + goto done; case 0: break; default: - return clib_error_return (0, "Unknown error: %d", rv); + error = clib_error_return (0, "Unknown error: %d", rv); + goto done; } vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index); - return 0; + +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (tap_connect_command, static) = { diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.c b/src/vnet/vxlan-gpe/vxlan_gpe.c index b97510c4..2cba596f 100644 --- a/src/vnet/vxlan-gpe/vxlan_gpe.c +++ b/src/vnet/vxlan-gpe/vxlan_gpe.c @@ -454,6 +454,7 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm, u32 tmp; vnet_vxlan_gpe_add_del_tunnel_args_t _a, * a = &_a; u32 sw_if_index; + clib_error_t *error = NULL; /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -494,7 +495,10 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm, encap_fib_index = ip4_fib_index_from_table_id (tmp); if (encap_fib_index == ~0) - return clib_error_return (0, "nonexistent encap fib id %d", tmp); + { + error = clib_error_return (0, "nonexistent encap fib id %d", tmp); + goto done; + } } else if (unformat (line_input, "decap-vrf-id %d", &tmp)) { @@ -504,7 +508,10 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm, decap_fib_index = ip4_fib_index_from_table_id (tmp); if (decap_fib_index == ~0) - return clib_error_return (0, "nonexistent decap fib id %d", tmp); + { + error = clib_error_return (0, "nonexistent decap fib id %d", tmp); + goto done; + } } else if (unformat (line_input, "vni %d", &vni)) vni_set = 1; @@ -517,27 +524,43 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm, else if (unformat(line_input, "next-nsh")) protocol = VXLAN_GPE_PROTOCOL_NSH; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (local_set == 0) - return clib_error_return (0, "tunnel local address not specified"); + { + error = clib_error_return (0, "tunnel local address not specified"); + goto done; + } if (remote_set == 0) - return clib_error_return (0, "tunnel remote address not specified"); + { + error = clib_error_return (0, "tunnel remote address not specified"); + goto done; + } if (ipv4_set && ipv6_set) - return clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + { + error = clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + goto done; + } if ((ipv4_set && memcmp(&local.ip4, &remote.ip4, sizeof(local.ip4)) == 0) || (ipv6_set && memcmp(&local.ip6, &remote.ip6, sizeof(local.ip6)) == 0)) - return clib_error_return (0, "src and dst addresses are identical"); + { + error = clib_error_return (0, "src and dst addresses are identical"); + goto done; + } if (vni_set == 0) - return clib_error_return (0, "vni not specified"); + { + error = clib_error_return (0, "vni not specified"); + goto done; + } memset (a, 0, sizeof (*a)); @@ -558,20 +581,27 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm, vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index); break; case VNET_API_ERROR_INVALID_DECAP_NEXT: - return clib_error_return (0, "invalid decap-next..."); + error = clib_error_return (0, "invalid decap-next..."); + goto done; case VNET_API_ERROR_TUNNEL_EXIST: - return clib_error_return (0, "tunnel already exists..."); + error = clib_error_return (0, "tunnel already exists..."); + goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "tunnel does not exist..."); + error = clib_error_return (0, "tunnel does not exist..."); + goto done; default: - return clib_error_return + error = clib_error_return (0, "vnet_vxlan_gpe_add_del_tunnel returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } VLIB_CLI_COMMAND (create_vxlan_gpe_tunnel_command, static) = { diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c index 849fc25d..eedc16f8 100644 --- a/src/vnet/vxlan/vxlan.c +++ b/src/vnet/vxlan/vxlan.c @@ -657,6 +657,7 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, int rv; vnet_vxlan_add_del_tunnel_args_t _a, * a = &_a; u32 tunnel_sw_if_index; + clib_error_t *error = NULL; /* Cant "universally zero init" (={0}) due to GCC bug 53119 */ memset(&src, 0, sizeof src); @@ -715,7 +716,10 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, { encap_fib_index = fib_table_find (fib_ip_proto (ipv6_set), tmp); if (encap_fib_index == ~0) - return clib_error_return (0, "nonexistent encap-vrf-id %d", tmp); + { + error = clib_error_return (0, "nonexistent encap-vrf-id %d", tmp); + goto done; + } } else if (unformat (line_input, "decap-next %U", unformat_decap_next, &decap_next_index, ipv4_set)) @@ -723,41 +727,72 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "vni %d", &vni)) { if (vni >> 24) - return clib_error_return (0, "vni %d out of range", vni); + { + error = clib_error_return (0, "vni %d out of range", vni); + goto done; + } } else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (src_set == 0) - return clib_error_return (0, "tunnel src address not specified"); + { + error = clib_error_return (0, "tunnel src address not specified"); + goto done; + } if (dst_set == 0) - return clib_error_return (0, "tunnel dst address not specified"); + { + error = clib_error_return (0, "tunnel dst address not specified"); + goto done; + } if (grp_set && !ip46_address_is_multicast(&dst)) - return clib_error_return (0, "tunnel group address not multicast"); + { + error = clib_error_return (0, "tunnel group address not multicast"); + goto done; + } if (grp_set == 0 && ip46_address_is_multicast(&dst)) - return clib_error_return (0, "dst address must be unicast"); + { + error = clib_error_return (0, "dst address must be unicast"); + goto done; + } if (grp_set && mcast_sw_if_index == ~0) - return clib_error_return (0, "tunnel nonexistent multicast device"); + { + error = clib_error_return (0, "tunnel nonexistent multicast device"); + goto done; + } if (ipv4_set && ipv6_set) - return clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + { + error = clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + goto done; + } if (ip46_address_cmp(&src, &dst) == 0) - return clib_error_return (0, "src and dst addresses are identical"); + { + error = clib_error_return (0, "src and dst addresses are identical"); + goto done; + } if (decap_next_index == ~0) - return clib_error_return (0, "next node not found"); + { + error = clib_error_return (0, "next node not found"); + goto done; + } if (vni == 0) - return clib_error_return (0, "vni not specified"); + { + error = clib_error_return (0, "vni not specified"); + goto done; + } memset (a, 0, sizeof (*a)); @@ -779,17 +814,23 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, break; case VNET_API_ERROR_TUNNEL_EXIST: - return clib_error_return (0, "tunnel already exists..."); + error = clib_error_return (0, "tunnel already exists..."); + goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "tunnel does not exist..."); + error = clib_error_return (0, "tunnel does not exist..."); + goto done; default: - return clib_error_return + error = clib_error_return (0, "vnet_vxlan_add_del_tunnel returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /*? @@ -912,6 +953,8 @@ set_ip_vxlan_bypass (u32 is_ip6, vnet_int_vxlan_bypass_mode (sw_if_index, is_ip6, is_enable); done: + unformat_free (line_input); + return error; } diff --git a/src/vpp/app/l2t.c b/src/vpp/app/l2t.c index 45dd2807..e1eda155 100644 --- a/src/vpp/app/l2t.c +++ b/src/vpp/app/l2t.c @@ -254,6 +254,7 @@ l2tp_session_add_command_fn (vlib_main_t * vm, u32 local_session_id = 1, remote_session_id = 1; int our_address_set = 0, client_address_set = 0; int l2_sublayer_present = 0; + clib_error_t *error = NULL; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -290,8 +291,12 @@ l2tp_session_add_command_fn (vlib_main_t * vm, else if (unformat (line_input, "l2-sublayer-present")) l2_sublayer_present = 1; else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + unformat_free (line_input); + return error; + } } unformat_free (line_input); diff --git a/src/vpp/app/vpe_cli.c b/src/vpp/app/vpe_cli.c index a26bf71f..94bdc84c 100644 --- a/src/vpp/app/vpe_cli.c +++ b/src/vpp/app/vpe_cli.c @@ -36,6 +36,7 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, mac_addr_t *mac_addrs = 0; u32 sw_if_index; u32 i; + clib_error_t *error = NULL; next_hops = NULL; rpaths = NULL; @@ -49,7 +50,11 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, if (!unformat (line_input, "%U %U", unformat_ip4_address, &prefix.fp_addr.ip4, unformat_vnet_sw_interface, vnm, &sw_if_index)) - goto barf; + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -67,13 +72,18 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, } else { - barf: - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; } } + if (vec_len (mac_addrs) == 0 || vec_len (mac_addrs) != vec_len (next_hops)) - goto barf; + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } /* Create / delete special interface route /32's */ @@ -100,10 +110,12 @@ virtual_ip_cmd_fn_command_fn (vlib_main_t * vm, &prefix, FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, rpaths); +done: vec_free (mac_addrs); vec_free (next_hops); + unformat_free (line_input); - return 0; + return error; } /* *INDENT-OFF* */ -- cgit 1.2.3-korg From 37be73693a46b05360483778efee3313a71654f5 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 21 Feb 2017 17:30:26 -0800 Subject: Tests to target holes in adjacency and DPO test coverage Change-Id: Ic6ac7e441a7b75baa02f03c1585d1ae00903a399 Signed-off-by: Neale Ranns --- src/vnet/gre/gre.c | 4 ++- test/test_ip4.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++- test/test_ip6.py | 71 ++++++++++++++++++++++++++++++++++++++++++- test/test_ip_mcast.py | 23 +++++++++++--- test/test_neighbor.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ test/vpp_interface.py | 7 +++++ test/vpp_ip_route.py | 31 +++++++++++++------ 7 files changed, 284 insertions(+), 16 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c index cd43a3af..29d0f0fe 100644 --- a/src/vnet/gre/gre.c +++ b/src/vnet/gre/gre.c @@ -241,7 +241,9 @@ gre_update_adj (vnet_main_t * vnm, adj_index_t ai) { adj_nbr_midchain_update_rewrite (ai, gre_fixup, - ADJ_MIDCHAIN_FLAG_NONE, + (VNET_LINK_ETHERNET == adj_get_link_type (ai) ? + ADJ_MIDCHAIN_FLAG_NO_COUNT : + ADJ_MIDCHAIN_FLAG_NONE), gre_build_rewrite(vnm, sw_if_index, adj_get_link_type(ai), NULL)); diff --git a/test/test_ip4.py b/test/test_ip4.py index 9bd9a458..7f6e92fa 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -5,10 +5,11 @@ import unittest from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint +from vpp_ip_route import VppIpRoute, VppRoutePath from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q -from scapy.layers.inet import IP, UDP +from scapy.layers.inet import IP, UDP, ICMP, icmptypes, icmpcodes from util import ppp @@ -465,5 +466,85 @@ class TestIPv4FibCrud(VppTestCase): self.verify_not_in_route_dump(fib_dump, self.deleted_routes) +class TestIPNull(VppTestCase): + """ IPv4 routes via NULL """ + + def setUp(self): + super(TestIPNull, self).setUp() + + # create 2 pg interfaces + self.create_pg_interfaces(range(1)) + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + + def tearDown(self): + super(TestIPNull, self).tearDown() + for i in self.pg_interfaces: + i.unconfig_ip4() + i.admin_down() + + def test_ip_null(self): + """ IP NULL route """ + + # + # A route via IP NULL that will reply with ICMP unreachables + # + ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1) + ip_unreach.add_vpp_config() + + p_unreach = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, dst="10.0.0.1") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.pg0.add_stream(p_unreach) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg0.get_capture(1) + rx = rx[0] + icmp = rx[ICMP] + + self.assertEqual(icmptypes[icmp.type], "dest-unreach") + self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable") + self.assertEqual(icmp.src, self.pg0.remote_ip4) + self.assertEqual(icmp.dst, "10.0.0.1") + + # + # ICMP replies are rate limited. so sit and spin. + # + self.sleep(1) + + # + # A route via IP NULL that will reply with ICMP prohibited + # + ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1) + ip_prohibit.add_vpp_config() + + p_prohibit = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, dst="10.0.0.2") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.pg0.add_stream(p_prohibit) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg0.get_capture(1) + + rx = rx[0] + icmp = rx[ICMP] + + self.assertEqual(icmptypes[icmp.type], "dest-unreach") + self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited") + self.assertEqual(icmp.src, self.pg0.remote_ip4) + self.assertEqual(icmp.dst, "10.0.0.2") + + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/test_ip6.py b/test/test_ip6.py index 070e2d7d..b95809b1 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -7,13 +7,14 @@ from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppSubInterface, VppDot1QSubint from vpp_pg_interface import is_ipv6_misc from vpp_neighbor import find_nbr +from vpp_ip_route import VppIpRoute, VppRoutePath from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q from scapy.layers.inet6 import IPv6, UDP, ICMPv6ND_NS, ICMPv6ND_RS, \ ICMPv6ND_RA, ICMPv6NDOptSrcLLAddr, getmacbyip6, ICMPv6MRD_Solicitation, \ ICMPv6NDOptMTU, ICMPv6NDOptSrcLLAddr, ICMPv6NDOptPrefixInfo, \ - ICMPv6ND_NA, ICMPv6NDOptDstLLAddr + ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, ICMPv6DestUnreach, icmp6types from util import ppp from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \ @@ -888,5 +889,73 @@ class IPv6NDProxyTest(TestIPv6ND): self.assertTrue(rx[0].haslayer(ICMPv6ND_NS)) +class TestIPNull(VppTestCase): + """ IPv6 routes via NULL """ + + def setUp(self): + super(TestIPNull, self).setUp() + + # create 2 pg interfaces + self.create_pg_interfaces(range(1)) + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip6() + i.resolve_ndp() + + def tearDown(self): + super(TestIPNull, self).tearDown() + for i in self.pg_interfaces: + i.unconfig_ip6() + i.admin_down() + + def test_ip_null(self): + """ IP NULL route """ + + p = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IPv6(src=self.pg0.remote_ip6, dst="2001::1") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + # + # A route via IP NULL that will reply with ICMP unreachables + # + ip_unreach = VppIpRoute(self, "2001::", 64, [], is_unreach=1, is_ip6=1) + ip_unreach.add_vpp_config() + + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg0.get_capture(1) + rx = rx[0] + icmp = rx[ICMPv6DestUnreach] + + # 0 = "No route to destination" + self.assertEqual(icmp.code, 0) + + # ICMP is rate limited. pause a bit + self.sleep(1) + + # + # A route via IP NULL that will reply with ICMP prohibited + # + ip_prohibit = VppIpRoute(self, "2001::1", 128, [], + is_prohibit=1, is_ip6=1) + ip_prohibit.add_vpp_config() + + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg0.get_capture(1) + rx = rx[0] + icmp = rx[ICMPv6DestUnreach] + + # 1 = "Communication with destination administratively prohibited" + self.assertEqual(icmp.code, 1) + + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/test_ip_mcast.py b/test/test_ip_mcast.py index 34ee417a..957bab5a 100644 --- a/test/test_ip_mcast.py +++ b/test/test_ip_mcast.py @@ -59,8 +59,8 @@ class TestIPMcast(VppTestCase): def setUp(self): super(TestIPMcast, self).setUp() - # create 4 pg interfaces - self.create_pg_interfaces(range(4)) + # create 8 pg interfaces + self.create_pg_interfaces(range(8)) # setup interfaces for i in self.pg_interfaces: @@ -176,7 +176,9 @@ class TestIPMcast(VppTestCase): # # A (*,G). - # one accepting interface, pg0, 3 forwarding interfaces + # one accepting interface, pg0, 7 forwarding interfaces + # many forwarding interfaces test the case where the replicare DPO + # needs to use extra cache lines for the buckets. # route_232_1_1_1 = VppIpMRoute( self, @@ -190,6 +192,14 @@ class TestIPMcast(VppTestCase): VppMRoutePath(self.pg2.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD), VppMRoutePath(self.pg3.sw_if_index, + MRouteItfFlags.MFIB_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg4.sw_if_index, + MRouteItfFlags.MFIB_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg5.sw_if_index, + MRouteItfFlags.MFIB_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg6.sw_if_index, + MRouteItfFlags.MFIB_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg7.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)]) route_232_1_1_1.add_vpp_config() @@ -235,9 +245,14 @@ class TestIPMcast(VppTestCase): self.pg_enable_capture(self.pg_interfaces) self.pg_start() - # We expect replications on Pg1, 2, + # We expect replications on Pg1->7 self.verify_capture_ip4(self.pg1, tx) self.verify_capture_ip4(self.pg2, tx) + self.verify_capture_ip4(self.pg3, tx) + self.verify_capture_ip4(self.pg4, tx) + self.verify_capture_ip4(self.pg5, tx) + self.verify_capture_ip4(self.pg6, tx) + self.verify_capture_ip4(self.pg7, tx) # no replications on Pg0 self.pg0.assert_nothing_captured( diff --git a/test/test_neighbor.py b/test/test_neighbor.py index 885bf5a4..2ce0a635 100644 --- a/test/test_neighbor.py +++ b/test/test_neighbor.py @@ -5,10 +5,12 @@ from socket import AF_INET, AF_INET6, inet_pton from framework import VppTestCase, VppTestRunner from vpp_neighbor import VppNeighbor, find_nbr +from vpp_ip_route import VppIpRoute, VppRoutePath from scapy.packet import Raw from scapy.layers.l2 import Ether, ARP from scapy.layers.inet import IP, UDP +from scapy.contrib.mpls import MPLS # not exported by scapy, so redefined here arp_opts = {"who-has": 1, "is-at": 2} @@ -88,6 +90,18 @@ class ARPTestCase(VppTestCase): self.assertEqual(ip.src, sip) self.assertEqual(ip.dst, dip) + def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip): + ether = rx[Ether] + self.assertEqual(ether.dst, dmac) + self.assertEqual(ether.src, smac) + + mpls = rx[MPLS] + self.assertTrue(mpls.label, label) + + ip = rx[IP] + self.assertEqual(ip.src, sip) + self.assertEqual(ip.dst, dip) + def send_and_assert_no_replies(self, intf, pkts, remark): intf.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) @@ -430,3 +444,70 @@ class ARPTestCase(VppTestCase): "ARP req from disable") self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable") + + # + # clean up on interface 2 + # + self.pg2.set_unnumbered(self.pg1.sw_if_index) + + def test_mpls(self): + """ MPLS """ + + # + # Interface 2 does not yet have ip4 config + # + self.pg2.config_ip4() + self.pg2.generate_remote_hosts(2) + + # + # Add a reoute with out going label via an ARP unresolved next-hop + # + ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, + [VppRoutePath(self.pg2.remote_hosts[1].ip4, + self.pg2.sw_if_index, + labels=[55])]) + ip_10_0_0_1.add_vpp_config() + + # + # packets should generate an ARP request + # + p = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, dst="10.0.0.1") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_req(rx[0], + self.pg2.local_mac, + self.pg2.local_ip4, + self.pg2._remote_hosts[1].ip4) + + # + # now resolve the neighbours + # + self.pg2.configure_ipv4_neighbors() + + # + # Now packet should be properly MPLS encapped. + # This verifies that MPLS link-type adjacencies are completed + # when the ARP entry resolves + # + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_ip_o_mpls(rx[0], + self.pg2.local_mac, + self.pg2.remote_hosts[1].mac, + 55, + self.pg0.remote_ip4, + "10.0.0.1") + +if __name__ == '__main__': + unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_interface.py b/test/vpp_interface.py index 53a0ae8d..8135bc84 100644 --- a/test/vpp_interface.py +++ b/test/vpp_interface.py @@ -335,6 +335,13 @@ class VppInterface(object): self.sw_if_index, ip_sw_if_index) + def unset_unnumbered(self, ip_sw_if_index): + """ Unaet the interface to unnumbered via ip_sw_if_index """ + self.test.vapi.sw_interface_set_unnumbered( + self.sw_if_index, + ip_sw_if_index, + is_add=0) + def set_proxy_arp(self, enable=1): """ Set the interface to enable/disable Proxy ARP """ self.test.vapi.proxy_arp_intfc_enable_disable( diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index f758c067..247263a3 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -46,26 +46,31 @@ class VppIpRoute(VppObject): """ def __init__(self, test, dest_addr, - dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0): + dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0, + is_unreach=0, is_prohibit=0): self._test = test self.paths = paths self.dest_addr_len = dest_addr_len self.table_id = table_id self.is_ip6 = is_ip6 self.is_local = is_local + self.is_unreach = is_unreach + self.is_prohibit = is_prohibit if is_ip6: self.dest_addr = socket.inet_pton(socket.AF_INET6, dest_addr) else: self.dest_addr = socket.inet_pton(socket.AF_INET, dest_addr) def add_vpp_config(self): - if self.is_local: + if self.is_local or self.is_unreach or self.is_prohibit: self._test.vapi.ip_add_del_route( self.dest_addr, self.dest_addr_len, socket.inet_pton(socket.AF_INET6, "::"), 0xffffffff, - is_local=1, + is_local=self.is_local, + is_unreach=self.is_unreach, + is_prohibit=self.is_prohibit, table_id=self.table_id, is_ipv6=self.is_ip6) else: @@ -84,13 +89,15 @@ class VppIpRoute(VppObject): self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): - if self.is_local: + if self.is_local or self.is_unreach or self.is_prohibit: self._test.vapi.ip_add_del_route( self.dest_addr, self.dest_addr_len, socket.inet_pton(socket.AF_INET6, "::"), 0xffffffff, - is_local=1, + is_local=self.is_local, + is_unreach=self.is_unreach, + is_prohibit=self.is_prohibit, is_add=0, table_id=self.table_id, is_ipv6=self.is_ip6) @@ -116,10 +123,16 @@ class VppIpRoute(VppObject): return self.object_id() def object_id(self): - return ("%d:%s/%d" - % (self.table_id, - socket.inet_ntop(socket.AF_INET, self.dest_addr), - self.dest_addr_len)) + if self.is_ip6: + return ("%d:%s/%d" + % (self.table_id, + socket.inet_ntop(socket.AF_INET6, self.dest_addr), + self.dest_addr_len)) + else: + return ("%d:%s/%d" + % (self.table_id, + socket.inet_ntop(socket.AF_INET, self.dest_addr), + self.dest_addr_len)) class VppIpMRoute(VppObject): -- cgit 1.2.3-korg From e9f929b52ddb741ec1e4cb2d92c6be1e798933a0 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Thu, 16 Mar 2017 11:32:09 +0100 Subject: vlib: make runtime_data thread-local Change-Id: I4aa3e7e42fb81211de1aed07dc7befee87a1e18b Signed-off-by: Damjan Marion --- src/vlib/init.h | 1 + src/vlib/main.h | 1 + src/vlib/node.c | 4 +- src/vlib/node.h | 81 +++++++++++++++++++++------------------- src/vlib/threads.c | 61 ++++++++++++++++++++++++++++-- src/vnet/gre/node.c | 26 ++++++++++--- src/vnet/hdlc/node.c | 27 +++++++++----- src/vnet/l2/l2_input_classify.c | 15 ++++++++ src/vnet/l2/l2_output_classify.c | 16 ++++++++ src/vnet/l2tp/l2tp.c | 10 +++++ src/vnet/mpls/node.c | 13 +++++++ src/vnet/ppp/node.c | 27 +++++++++----- src/vnet/tcp/tcp_syn_filter4.c | 23 +++++++----- src/vnet/udp/udp_local.c | 74 ++++++++++++++++++++++-------------- 14 files changed, 273 insertions(+), 106 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/vlib/init.h b/src/vlib/init.h index 4fa5b304..12db3f90 100644 --- a/src/vlib/init.h +++ b/src/vlib/init.h @@ -109,6 +109,7 @@ static void __vlib_add_##tag##_function_##x (void) \ } #define VLIB_INIT_FUNCTION(x) VLIB_DECLARE_INIT_FUNCTION(x,init) +#define VLIB_WORKER_INIT_FUNCTION(x) VLIB_DECLARE_INIT_FUNCTION(x,worker_init) #define VLIB_MAIN_LOOP_ENTER_FUNCTION(x) \ VLIB_DECLARE_INIT_FUNCTION(x,main_loop_enter) diff --git a/src/vlib/main.h b/src/vlib/main.h index a6d50b39..98bc823d 100644 --- a/src/vlib/main.h +++ b/src/vlib/main.h @@ -162,6 +162,7 @@ typedef struct vlib_main_t /* List of init functions to call, setup by constructors */ _vlib_init_function_list_elt_t *init_function_registrations; + _vlib_init_function_list_elt_t *worker_init_function_registrations; _vlib_init_function_list_elt_t *main_loop_enter_function_registrations; _vlib_init_function_list_elt_t *main_loop_exit_function_registrations; _vlib_init_function_list_elt_t *api_init_function_registrations; diff --git a/src/vlib/node.c b/src/vlib/node.c index c419a13a..dc0a4de5 100644 --- a/src/vlib/node.c +++ b/src/vlib/node.c @@ -434,9 +434,7 @@ register_node (vlib_main_t * vm, vlib_node_registration_t * r) rt->errors[i] = vlib_error_set (n->index, i); STATIC_ASSERT_SIZEOF (vlib_node_runtime_t, 128); - ASSERT (vec_len (n->runtime_data) <= - sizeof (vlib_node_runtime_t) - - STRUCT_OFFSET_OF (vlib_node_runtime_t, runtime_data)); + ASSERT (vec_len (n->runtime_data) <= VLIB_NODE_RUNTIME_DATA_SIZE); if (vec_len (n->runtime_data) > 0) clib_memcpy (rt->runtime_data, n->runtime_data, diff --git a/src/vlib/node.h b/src/vlib/node.h index b624e9d6..2a532cc3 100644 --- a/src/vlib/node.h +++ b/src/vlib/node.h @@ -411,65 +411,68 @@ typedef struct typedef struct vlib_node_runtime_t { - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - /* Node function to call. */ - vlib_node_function_t *function; + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); /**< cacheline mark */ - /* Vector of errors for this node. */ - vlib_error_t *errors; + vlib_node_function_t *function; /**< Node function to call. */ - /* Number of clock cycles. */ - u32 clocks_since_last_overflow; + vlib_error_t *errors; /**< Vector of errors for this node. */ - /* Maximum clock cycle for an invocation. */ - u32 max_clock; + u32 clocks_since_last_overflow; /**< Number of clock cycles. */ - /* Number of vectors in the recorded max_clock. */ - u32 max_clock_n; + u32 max_clock; /**< Maximum clock cycle for an + invocation. */ - /* Number of calls. */ - u32 calls_since_last_overflow; + u32 max_clock_n; /**< Number of vectors in the recorded + max_clock. */ - /* Number of vector elements processed by this node. */ - u32 vectors_since_last_overflow; + u32 calls_since_last_overflow; /**< Number of calls. */ - /* Start of next frames for this node. */ - u32 next_frame_index; + u32 vectors_since_last_overflow; /**< Number of vector elements + processed by this node. */ - /* Node index. */ - u32 node_index; + u32 next_frame_index; /**< Start of next frames for this + node. */ - /* For input nodes: decremented on each main loop interation until it reaches zero - and function is called. Allows some input nodes to be called - more than others. */ - u32 input_main_loops_per_call; + u32 node_index; /**< Node index. */ - /* Saved main loop counter of last dispatch of this node. */ - u32 main_loop_count_last_dispatch; + u32 input_main_loops_per_call; /**< For input nodes: decremented + on each main loop interation until + it reaches zero and function is + called. Allows some input nodes to + be called more than others. */ + + u32 main_loop_count_last_dispatch; /**< Saved main loop counter of last + dispatch of this node. */ u32 main_loop_vector_stats[2]; - /* Copy of main node flags. */ - u16 flags; + u16 flags; /**< Copy of main node flags. */ - /* Input node state. */ - u16 state; + u16 state; /**< Input node state. */ u16 n_next_nodes; - /* Next frame index that vector arguments were last enqueued to - last time this node ran. Set to zero before first run - of this node. */ - u16 cached_next_index; - - /* CPU this node runs on */ - u16 cpu_index; - - /* Function dependent node-runtime. */ - u8 runtime_data[0]; + u16 cached_next_index; /**< Next frame index that vector + arguments were last enqueued to + last time this node ran. Set to + zero before first run of this + node. */ + + u16 cpu_index; /**< CPU this node runs on */ + + u8 runtime_data[0]; /**< Function dependent + node-runtime data. This data is + thread local, and it is not + cloned from main thread. It needs + to be initialized for each thread + before it is used unless + runtime_data template exists in + vlib_node_t. */ } vlib_node_runtime_t; +#define VLIB_NODE_RUNTIME_DATA_SIZE (sizeof (vlib_node_runtime_t) - STRUCT_OFFSET_OF (vlib_node_runtime_t, runtime_data)) + typedef struct { /* Number of allocated frames for this scalar/vector size. */ diff --git a/src/vlib/threads.c b/src/vlib/threads.c index 07dbff33..3756c3fa 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -633,6 +633,8 @@ start_workers (vlib_main_t * vm) vm_clone->cpu_index = worker_thread_index; vm_clone->heap_base = w->thread_mheap; vm_clone->mbuf_alloc_list = 0; + vm_clone->init_functions_called = + hash_create (0, /* value bytes */ 0); memset (&vm_clone->random_buffer, 0, sizeof (vm_clone->random_buffer)); @@ -674,11 +676,33 @@ start_workers (vlib_main_t * vm) } nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] = vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]); + vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) + { + vlib_node_t *n = vlib_get_node (vm, rt->node_index); + rt->cpu_index = vm_clone->cpu_index; + /* copy initial runtime_data from node */ + if (n->runtime_data_bytes > 0) + clib_memcpy (rt->runtime_data, n->runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); + else if (CLIB_DEBUG > 0) + memset (rt->runtime_data, 0xfe, + VLIB_NODE_RUNTIME_DATA_SIZE); + } nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] = vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]); vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) + { + vlib_node_t *n = vlib_get_node (vm, rt->node_index); rt->cpu_index = vm_clone->cpu_index; + /* copy initial runtime_data from node */ + if (n->runtime_data_bytes > 0) + clib_memcpy (rt->runtime_data, n->runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); + else if (CLIB_DEBUG > 0) + memset (rt->runtime_data, 0xfe, + VLIB_NODE_RUNTIME_DATA_SIZE); + } nm_clone->processes = vec_dup (nm->processes); @@ -926,26 +950,51 @@ vlib_worker_thread_node_runtime_update (void) clib_mem_free (old_nodes_clone[j]); vec_free (old_nodes_clone); - vec_free (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]); + /* re-clone internal nodes */ + old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]; nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] = vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]); - /* clone input node runtime */ - old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]; + vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]) + { + vlib_node_t *n = vlib_get_node (vm, rt->node_index); + rt->cpu_index = vm_clone->cpu_index; + /* copy runtime_data, will be overwritten later for existing rt */ + clib_memcpy (rt->runtime_data, n->runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); + } + + for (j = 0; j < vec_len (old_rt); j++) + { + rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index); + rt->state = old_rt[j].state; + clib_memcpy (rt->runtime_data, old_rt[j].runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); + } + vec_free (old_rt); + + /* re-clone input nodes */ + old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]; nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] = vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]); vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) { + vlib_node_t *n = vlib_get_node (vm, rt->node_index); rt->cpu_index = vm_clone->cpu_index; + /* copy runtime_data, will be overwritten later for existing rt */ + clib_memcpy (rt->runtime_data, n->runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); } for (j = 0; j < vec_len (old_rt); j++) { rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index); rt->state = old_rt[j].state; + clib_memcpy (rt->runtime_data, old_rt[j].runtime_data, + VLIB_NODE_RUNTIME_DATA_SIZE); } vec_free (old_rt); @@ -1342,6 +1391,7 @@ vlib_worker_thread_fn (void *arg) vlib_worker_thread_t *w = (vlib_worker_thread_t *) arg; vlib_thread_main_t *tm = vlib_get_thread_main (); vlib_main_t *vm = vlib_get_main (); + clib_error_t *e; ASSERT (vm->cpu_index == os_get_cpu_number ()); @@ -1349,6 +1399,11 @@ vlib_worker_thread_fn (void *arg) clib_time_init (&vm->clib_time); clib_mem_set_heap (w->thread_mheap); + e = vlib_call_init_exit_functions + (vm, vm->worker_init_function_registrations, 1 /* call_once */ ); + if (e) + clib_error_report (e); + /* Wait until the dpdk init sequence is complete */ while (tm->extern_thread_mgmt && tm->worker_thread_release == 0) vlib_worker_thread_barrier_check (); diff --git a/src/vnet/gre/node.c b/src/vnet/gre/node.c index 86f7a6ee..dd16db5e 100644 --- a/src/vnet/gre/node.c +++ b/src/vnet/gre/node.c @@ -448,7 +448,6 @@ gre_register_input_protocol (vlib_main_t * vm, { gre_main_t * em = &gre_main; gre_protocol_info_t * pi; - gre_input_runtime_t * rt; u16 * n; { @@ -464,10 +463,13 @@ gre_register_input_protocol (vlib_main_t * vm, node_index); /* Setup gre protocol -> next index sparse vector mapping. */ - rt = vlib_node_get_runtime_data (vm, gre_input_node.index); - n = sparse_vec_validate (rt->next_by_protocol, - clib_host_to_net_u16 (protocol)); - n[0] = pi->next_index; + foreach_vlib_main ({ + gre_input_runtime_t * rt; + rt = vlib_node_get_runtime_data (this_vlib_main, gre_input_node.index); + n = sparse_vec_validate (rt->next_by_protocol, + clib_host_to_net_u16 (protocol)); + n[0] = pi->next_index; + }); } static void @@ -529,3 +531,17 @@ static clib_error_t * gre_input_init (vlib_main_t * vm) } VLIB_INIT_FUNCTION (gre_input_init); + +static clib_error_t * gre_input_worker_init (vlib_main_t * vm) +{ + gre_input_runtime_t * rt; + + rt = vlib_node_get_runtime_data (vm, gre_input_node.index); + + rt->next_by_protocol = sparse_vec_new + (/* elt bytes */ sizeof (rt->next_by_protocol[0]), + /* bits in index */ BITS (((gre_header_t *) 0)->protocol)); + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (gre_input_worker_init); diff --git a/src/vnet/hdlc/node.c b/src/vnet/hdlc/node.c index 4fe0296a..57e04c85 100644 --- a/src/vnet/hdlc/node.c +++ b/src/vnet/hdlc/node.c @@ -285,18 +285,9 @@ VLIB_REGISTER_NODE (hdlc_input_node) = { .unformat_buffer = unformat_hdlc_header, }; -static clib_error_t * hdlc_input_init (vlib_main_t * vm) +static clib_error_t * hdlc_input_runtime_init (vlib_main_t * vm) { hdlc_input_runtime_t * rt; - - { - clib_error_t * error = vlib_call_init_function (vm, hdlc_init); - if (error) - clib_error_report (error); - } - - hdlc_setup_node (vm, hdlc_input_node.index); - rt = vlib_node_get_runtime_data (vm, hdlc_input_node.index); rt->next_by_protocol = sparse_vec_new @@ -313,7 +304,23 @@ static clib_error_t * hdlc_input_init (vlib_main_t * vm) return 0; } +static clib_error_t * hdlc_input_init (vlib_main_t * vm) +{ + + { + clib_error_t * error = vlib_call_init_function (vm, hdlc_init); + if (error) + clib_error_report (error); + } + + hdlc_setup_node (vm, hdlc_input_node.index); + hdlc_input_runtime_init (vm); + + return 0; +} + VLIB_INIT_FUNCTION (hdlc_input_init); +VLIB_WORKER_INIT_FUNCTION (hdlc_input_runtime_init); void hdlc_register_input_protocol (vlib_main_t * vm, diff --git a/src/vnet/l2/l2_input_classify.c b/src/vnet/l2/l2_input_classify.c index 497df192..485b9abd 100644 --- a/src/vnet/l2/l2_input_classify.c +++ b/src/vnet/l2/l2_input_classify.c @@ -505,6 +505,21 @@ l2_input_classify_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (l2_input_classify_init); +clib_error_t * +l2_input_classify_worker_init (vlib_main_t * vm) +{ + l2_input_classify_main_t *cm = &l2_input_classify_main; + l2_input_classify_runtime_t *rt; + + rt = vlib_node_get_runtime_data (vm, l2_input_classify_node.index); + + rt->l2cm = cm; + rt->vcm = cm->vnet_classify_main; + + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (l2_input_classify_worker_init); /** Enable/disable l2 input classification on a specific interface. */ void diff --git a/src/vnet/l2/l2_output_classify.c b/src/vnet/l2/l2_output_classify.c index 832be1a1..c1bdaddc 100644 --- a/src/vnet/l2/l2_output_classify.c +++ b/src/vnet/l2/l2_output_classify.c @@ -505,6 +505,22 @@ l2_output_classify_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (l2_output_classify_init); +clib_error_t * +l2_output_classify_worker_init (vlib_main_t * vm) +{ + l2_output_classify_main_t *cm = &l2_output_classify_main; + l2_output_classify_runtime_t *rt; + + rt = vlib_node_get_runtime_data (vm, l2_output_classify_node.index); + + rt->l2cm = cm; + rt->vcm = cm->vnet_classify_main; + + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (l2_output_classify_worker_init); + /** Enable/disable l2 input classification on a specific interface. */ void vnet_l2_output_classify_enable_disable (u32 sw_if_index, int enable_disable) diff --git a/src/vnet/l2tp/l2tp.c b/src/vnet/l2tp/l2tp.c index 2d323397..cb94d7e7 100644 --- a/src/vnet/l2tp/l2tp.c +++ b/src/vnet/l2tp/l2tp.c @@ -747,6 +747,16 @@ l2tp_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (l2tp_init); +clib_error_t * +l2tp_worker_init (vlib_main_t * vm) +{ + l2tp_encap_init (vm); + + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (l2tp_worker_init); + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/mpls/node.c b/src/vnet/mpls/node.c index 18100912..03bfaf56 100644 --- a/src/vnet/mpls/node.c +++ b/src/vnet/mpls/node.c @@ -301,3 +301,16 @@ static clib_error_t * mpls_input_init (vlib_main_t * vm) } VLIB_INIT_FUNCTION (mpls_input_init); + +static clib_error_t * mpls_input_worker_init (vlib_main_t * vm) +{ + mpls_input_runtime_t * rt; + rt = vlib_node_get_runtime_data (vm, mpls_input_node.index); + rt->last_label = (u32) ~0; + rt->last_inner_fib_index = 0; + rt->last_outer_fib_index = 0; + rt->mpls_main = &mpls_main; + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (mpls_input_worker_init); diff --git a/src/vnet/ppp/node.c b/src/vnet/ppp/node.c index 4f1f6a71..2f6e0c33 100644 --- a/src/vnet/ppp/node.c +++ b/src/vnet/ppp/node.c @@ -295,18 +295,10 @@ VLIB_REGISTER_NODE (ppp_input_node) = { /* *INDENT-ON* */ static clib_error_t * -ppp_input_init (vlib_main_t * vm) +ppp_input_runtime_init (vlib_main_t * vm) { ppp_input_runtime_t *rt; - { - clib_error_t *error = vlib_call_init_function (vm, ppp_init); - if (error) - clib_error_report (error); - } - - ppp_setup_node (vm, ppp_input_node.index); - rt = vlib_node_get_runtime_data (vm, ppp_input_node.index); rt->next_by_protocol = sparse_vec_new @@ -323,7 +315,24 @@ ppp_input_init (vlib_main_t * vm) return 0; } +static clib_error_t * +ppp_input_init (vlib_main_t * vm) +{ + + { + clib_error_t *error = vlib_call_init_function (vm, ppp_init); + if (error) + clib_error_report (error); + } + + ppp_setup_node (vm, ppp_input_node.index); + ppp_input_runtime_init (vm); + + return 0; +} + VLIB_INIT_FUNCTION (ppp_input_init); +VLIB_WORKER_INIT_FUNCTION (ppp_input_runtime_init); void ppp_register_input_protocol (vlib_main_t * vm, diff --git a/src/vnet/tcp/tcp_syn_filter4.c b/src/vnet/tcp/tcp_syn_filter4.c index c7605a30..9b2a8ac7 100644 --- a/src/vnet/tcp/tcp_syn_filter4.c +++ b/src/vnet/tcp/tcp_syn_filter4.c @@ -450,18 +450,21 @@ syn_filter_enable_disable (u32 sw_if_index, int enable_disable) if (enable_disable) { - vlib_main_t *vm = vlib_get_main (); syn_filter4_runtime_t *rt; - rt = vlib_node_get_runtime_data (vm, syn_filter4_node.index); - vec_validate (rt->syn_counts, 1023); - /* - * Given perfect disperson / optimal hashing results: - * Allow 128k (successful) syns/sec. 1024, buckets each of which - * absorb 128 syns before filtering. Reset table once a second. - * Reality bites, lets try resetting once every 100ms. - */ - rt->reset_interval = 0.1; /* reset interval in seconds */ + /* *INDENT-OFF* */ + foreach_vlib_main ({ + rt = vlib_node_get_runtime_data (this_vlib_main, syn_filter4_node.index); + vec_validate (rt->syn_counts, 1023); + /* + * Given perfect disperson / optimal hashing results: + * Allow 128k (successful) syns/sec. 1024, buckets each of which + * absorb 128 syns before filtering. Reset table once a second. + * Reality bites, lets try resetting once every 100ms. + */ + rt->reset_interval = 0.1; /* reset interval in seconds */ + }); + /* *INDENT-ON* */ } rv = vnet_feature_enable_disable ("ip4-local", "syn-filter-4", diff --git a/src/vnet/udp/udp_local.c b/src/vnet/udp/udp_local.c index 6b239f73..3a60b29b 100644 --- a/src/vnet/udp/udp_local.c +++ b/src/vnet/udp/udp_local.c @@ -520,11 +520,15 @@ udp_register_dst_port (vlib_main_t * vm, : udp6_input_node.index, node_index); /* Setup udp protocol -> next index sparse vector mapping. */ - rt = vlib_node_get_runtime_data - (vm, is_ip4 ? udp4_input_node.index : udp6_input_node.index); - n = sparse_vec_validate (rt->next_by_dst_port, - clib_host_to_net_u16 (dst_port)); - n[0] = pi->next_index; + /* *INDENT-OFF* */ + foreach_vlib_main({ + rt = vlib_node_get_runtime_data + (this_vlib_main, is_ip4 ? udp4_input_node.index : udp6_input_node.index); + n = sparse_vec_validate (rt->next_by_dst_port, + clib_host_to_net_u16 (dst_port)); + n[0] = pi->next_index; + }); + /* *INDENT-ON* */ } void @@ -541,11 +545,15 @@ udp_unregister_dst_port (vlib_main_t * vm, udp_dst_port_t dst_port, u8 is_ip4) return; /* Kill the mapping. Don't bother killing the pi, it may be back. */ - rt = vlib_node_get_runtime_data - (vm, is_ip4 ? udp4_input_node.index : udp6_input_node.index); - n = sparse_vec_validate (rt->next_by_dst_port, - clib_host_to_net_u16 (dst_port)); - n[0] = SPARSE_VEC_INVALID_INDEX; + /* *INDENT-OFF* */ + foreach_vlib_main({ + rt = vlib_node_get_runtime_data + (this_vlib_main, is_ip4 ? udp4_input_node.index : udp6_input_node.index); + n = sparse_vec_validate (rt->next_by_dst_port, + clib_host_to_net_u16 (dst_port)); + n[0] = SPARSE_VEC_INVALID_INDEX; + }); + /* *INDENT-ON* */ } void @@ -604,10 +612,27 @@ udp_setup_node (vlib_main_t * vm, u32 node_index) pn->unformat_edit = unformat_pg_udp_header; } +static void +udp_local_node_runtime_init (vlib_main_t * vm) +{ + udp_input_runtime_t *rt; + + rt = vlib_node_get_runtime_data (vm, udp4_input_node.index); + rt->next_by_dst_port = sparse_vec_new + ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]), + /* bits in index */ BITS (((udp_header_t *) 0)->dst_port)); + rt->punt_unknown = 0; + + rt = vlib_node_get_runtime_data (vm, udp6_input_node.index); + rt->next_by_dst_port = sparse_vec_new + ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]), + /* bits in index */ BITS (((udp_header_t *) 0)->dst_port)); + rt->punt_unknown = 0; +} + clib_error_t * udp_local_init (vlib_main_t * vm) { - udp_input_runtime_t *rt; udp_main_t *um = &udp_main; int i; @@ -628,27 +653,13 @@ udp_local_init (vlib_main_t * vm) udp_setup_node (vm, udp4_input_node.index); udp_setup_node (vm, udp6_input_node.index); - rt = vlib_node_get_runtime_data (vm, udp4_input_node.index); - - rt->next_by_dst_port = sparse_vec_new - ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]), - /* bits in index */ BITS (((udp_header_t *) 0)->dst_port)); - - rt->punt_unknown = 0; + udp_local_node_runtime_init (vm); #define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 1 /* is_ip4 */); foreach_udp4_dst_port #undef _ - rt = vlib_node_get_runtime_data (vm, udp6_input_node.index); - - rt->next_by_dst_port = sparse_vec_new - ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]), - /* bits in index */ BITS (((udp_header_t *) 0)->dst_port)); - - rt->punt_unknown = 0; - #define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 0 /* is_ip4 */); - foreach_udp6_dst_port + foreach_udp6_dst_port #undef _ ip4_register_protocol (IP_PROTOCOL_UDP, udp4_input_node.index); /* Note: ip6 differs from ip4, UDP is hotwired to ip6-udp-lookup */ @@ -657,6 +668,15 @@ udp_local_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (udp_local_init); +clib_error_t * +udp_local_worker_init (vlib_main_t * vm) +{ + udp_local_node_runtime_init (vm); + return 0; +} + +VLIB_WORKER_INIT_FUNCTION (udp_local_worker_init); + /* * fd.io coding-style-patch-verification: ON * -- cgit 1.2.3-korg From fa5d19829759cef45cc34efe844d9471f5a1fc61 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 20 Feb 2017 14:19:51 -0800 Subject: Adjacency layout change and move to vnet/adj Change-Id: I03195a86c69f84a301051c6b3ab64456bbf28645 Signed-off-by: Neale Ranns --- src/vnet.am | 9 +- src/vnet/adj/adj.c | 3 +- src/vnet/adj/adj.h | 220 ++++++++++++++++++++- src/vnet/adj/adj_midchain.c | 25 ++- src/vnet/adj/adj_midchain.h | 22 +-- src/vnet/adj/adj_nbr.c | 8 +- src/vnet/adj/rewrite.c | 234 ++++++++++++++++++++++ src/vnet/adj/rewrite.h | 350 +++++++++++++++++++++++++++++++++ src/vnet/ethernet/arp.c | 1 - src/vnet/gre/gre.c | 4 +- src/vnet/ip/ip6_neighbor.c | 1 - src/vnet/ip/lookup.c | 10 +- src/vnet/ip/lookup.h | 209 +------------------- src/vnet/lisp-gpe/lisp_gpe_adjacency.c | 4 +- src/vnet/mpls/mpls_tunnel.c | 2 +- src/vnet/rewrite.c | 234 ---------------------- src/vnet/rewrite.h | 350 --------------------------------- 17 files changed, 837 insertions(+), 849 deletions(-) create mode 100644 src/vnet/adj/rewrite.c create mode 100644 src/vnet/adj/rewrite.h delete mode 100644 src/vnet/rewrite.c delete mode 100644 src/vnet/rewrite.h (limited to 'src/vnet/gre') diff --git a/src/vnet.am b/src/vnet.am index 823dd0d6..f95ec2fb 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -40,8 +40,7 @@ libvnet_la_SOURCES += \ vnet/interface_format.c \ vnet/interface_output.c \ vnet/misc.c \ - vnet/replication.c \ - vnet/rewrite.c + vnet/replication.c nobase_include_HEADERS += \ vnet/api_errno.h \ @@ -963,14 +962,16 @@ libvnet_la_SOURCES += \ vnet/adj/adj_mcast.c \ vnet/adj/adj_l2.c \ vnet/adj/adj_nsh.c \ - vnet/adj/adj.c + vnet/adj/adj.c \ + vnet/adj/rewrite.c nobase_include_HEADERS += \ vnet/adj/adj.h \ vnet/adj/adj_types.h \ vnet/adj/adj_glean.h \ vnet/adj/adj_nsh.h \ - vnet/adj/adj_nbr.h + vnet/adj/adj_nbr.h \ + vnet/adj/rewrite.h ######################################## # Data-Plane Objects diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index c1d036a0..7cf9e9d0 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -48,7 +48,7 @@ adj_alloc (fib_protocol_t proto) { ip_adjacency_t *adj; - pool_get(adj_pool, adj); + pool_get_aligned(adj_pool, adj, CLIB_CACHE_LINE_BYTES); adj_poison(adj); @@ -58,7 +58,6 @@ adj_alloc (fib_protocol_t proto) adj_get_index(adj)); adj->rewrite_header.sw_if_index = ~0; - adj->n_adj = 1; adj->lookup_next_index = 0; fib_node_init(&adj->ia_node, diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h index 271fdbc6..af7730f7 100644 --- a/src/vnet/adj/adj.h +++ b/src/vnet/adj/adj.h @@ -24,7 +24,6 @@ * address in the ARP packet. * UNSHARED. Only one per-interface. * - midchain: a nighbour adj on a virtual/tunnel interface. - * - rewrite: an adj with no key, but with a rewrite string. * * The API to create and update the adjacency is very sub-type specific. This * is intentional as it encourages the user to carefully consider which adjacency @@ -42,10 +41,227 @@ #ifndef __ADJ_H__ #define __ADJ_H__ -#include #include #include #include +#include + +/** @brief Common (IP4/IP6) next index stored in adjacency. */ +typedef enum +{ + /** Adjacency to drop this packet. */ + IP_LOOKUP_NEXT_DROP, + /** Adjacency to punt this packet. */ + IP_LOOKUP_NEXT_PUNT, + + /** This packet is for one of our own IP addresses. */ + IP_LOOKUP_NEXT_LOCAL, + + /** This packet matches an "incomplete adjacency" and packets + need to be passed to ARP to find rewrite string for + this destination. */ + IP_LOOKUP_NEXT_ARP, + + /** This packet matches an "interface route" and packets + need to be passed to ARP to find rewrite string for + this destination. */ + IP_LOOKUP_NEXT_GLEAN, + + /** This packet is to be rewritten and forwarded to the next + processing node. This is typically the output interface but + might be another node for further output processing. */ + IP_LOOKUP_NEXT_REWRITE, + + /** This packets follow a mid-chain adjacency */ + IP_LOOKUP_NEXT_MIDCHAIN, + + /** This packets needs to go to ICMP error */ + IP_LOOKUP_NEXT_ICMP_ERROR, + + /** Multicast Adjacency. */ + IP_LOOKUP_NEXT_MCAST, + + IP_LOOKUP_N_NEXT, +} __attribute__ ((packed)) ip_lookup_next_t; + +typedef enum +{ + IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT, +} ip4_lookup_next_t; + +typedef enum +{ + /* Hop-by-hop header handling */ + IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT, + IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP, + IP6_LOOKUP_NEXT_POP_HOP_BY_HOP, + IP6_LOOKUP_N_NEXT, +} ip6_lookup_next_t; + +#define IP4_LOOKUP_NEXT_NODES { \ + [IP_LOOKUP_NEXT_DROP] = "ip4-drop", \ + [IP_LOOKUP_NEXT_PUNT] = "ip4-punt", \ + [IP_LOOKUP_NEXT_LOCAL] = "ip4-local", \ + [IP_LOOKUP_NEXT_ARP] = "ip4-arp", \ + [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \ + [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \ + [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \ + [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \ + [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \ +} + +#define IP6_LOOKUP_NEXT_NODES { \ + [IP_LOOKUP_NEXT_DROP] = "ip6-drop", \ + [IP_LOOKUP_NEXT_PUNT] = "ip6-punt", \ + [IP_LOOKUP_NEXT_LOCAL] = "ip6-local", \ + [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \ + [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \ + [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \ + [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \ + [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \ + [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error", \ + [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \ + [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \ + [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \ +} + +/** + * Forward delcartion + */ +struct ip_adjacency_t_; + +/** + * @brief A function type for post-rewrite fixups on midchain adjacency + */ +typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm, + struct ip_adjacency_t_ * adj, + vlib_buffer_t * b0); + +/** + * @brief Flags on an IP adjacency + */ +typedef enum ip_adjacency_flags_t_ +{ + ADJ_FLAG_NONE = 0, + + /** + * Currently a sync walk is active. Used to prevent re-entrant walking + */ + ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0), + + /** + * Packets TX through the midchain do not increment the interface + * counters. This should be used when the adj is associated with an L2 + * interface and that L2 interface is in a bridege domain. In that case + * the packet will have traversed the interface's TX node, and hence have + * been counted, before it traverses ths midchain + */ + ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1), +} __attribute__ ((packed)) adj_flags_t; + +/** + * @brief IP unicast adjacency. + * @note cache aligned. + * + * An adjacency is a represenation of a peer on a particular link. + */ +typedef struct ip_adjacency_t_ +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + + /** + * Linkage into the FIB node grpah. First member since this type + * has 8 byte alignment requirements. + */ + fib_node_t ia_node; + + /** + * Next hop after ip4-lookup. + * This is not accessed in the rewrite nodes. + * 1-bytes + */ + ip_lookup_next_t lookup_next_index; + + /** + * link/ether-type + * 1 bytes + */ + vnet_link_t ia_link; + + /** + * The protocol of the neighbor/peer. i.e. the protocol with + * which to interpret the 'next-hop' attirbutes of the sub-types. + * 1-btyes + */ + fib_protocol_t ia_nh_proto; + + /** + * Flags on the adjacency + * 1-bytes + */ + adj_flags_t ia_flags; + + union + { + /** + * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE + * + * neighbour adjacency sub-type; + */ + struct + { + ip46_address_t next_hop; + } nbr; + /** + * IP_LOOKUP_NEXT_MIDCHAIN + * + * A nbr adj that is also recursive. Think tunnels. + * A nbr adj can transition to be of type MDICHAIN + * so be sure to leave the two structs with the next_hop + * fields aligned. + */ + struct + { + /** + * The recursive next-hop. + * This field MUST be at the same memory location as + * sub_type.nbr.next_hop + */ + ip46_address_t next_hop; + /** + * The next DPO to use + */ + dpo_id_t next_dpo; + /** + * A function to perform the post-rewrite fixup + */ + adj_midchain_fixup_t fixup_func; + } midchain; + /** + * IP_LOOKUP_NEXT_GLEAN + * + * Glean the address to ARP for from the packet's destination. + * Technically these aren't adjacencies, i.e. they are not a + * representation of a peer. One day we might untangle this coupling + * and use a new Glean DPO. + */ + struct + { + ip46_address_t receive_addr; + } glean; + } sub_type; + + CLIB_CACHE_LINE_ALIGN_MARK (cacheline1); + + /* Rewrite in second/third cache lines */ + vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE); +} ip_adjacency_t; + +STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0), + "IP adjacency cachline 0 is not offset"); +STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) == + CLIB_CACHE_LINE_BYTES), + "IP adjacency cachline 1 is more than one cachline size offset"); /** * @brief diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c index 55b5e44b..e8087f08 100644 --- a/src/vnet/adj/adj_midchain.c +++ b/src/vnet/adj/adj_midchain.c @@ -384,6 +384,14 @@ adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj) return (arc); } +static u32 +adj_nbr_midchain_get_tx_node (ip_adjacency_t *adj) +{ + return ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ? + adj_midchain_tx_no_count_node.index : + adj_midchain_tx_node.index); +} + /** * adj_nbr_midchain_update_rewrite * @@ -394,12 +402,12 @@ adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj) void adj_nbr_midchain_update_rewrite (adj_index_t adj_index, adj_midchain_fixup_t fixup, - adj_midchain_flag_t flags, + adj_flags_t flags, u8 *rewrite) { + u32 feature_index, tx_node; ip_adjacency_t *adj; u8 arc_index; - u32 feature_index; ASSERT(ADJ_INDEX_INVALID != adj_index); @@ -416,15 +424,14 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index, ASSERT(NULL != rewrite); adj->sub_type.midchain.fixup_func = fixup; + adj->ia_flags |= flags; arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj); - feature_index = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ? + feature_index = (flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ? adj_midchain_tx_no_count_feature_node[adj->ia_link] : adj_midchain_tx_feature_node[adj->ia_link]; - adj->sub_type.midchain.tx_function_node = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ? - adj_midchain_tx_no_count_node.index : - adj_midchain_tx_node.index; + tx_node = adj_nbr_midchain_get_tx_node(adj); vnet_feature_enable_disable_with_index (arc_index, feature_index, adj->rewrite_header.sw_if_index, @@ -437,7 +444,7 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index, * node are any output features, then the midchain-tx. from there we * need to get to the stacked child's node. */ - dpo_stack_from_node(adj->sub_type.midchain.tx_function_node, + dpo_stack_from_node(tx_node, &adj->sub_type.midchain.next_dpo, drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link))); @@ -447,7 +454,7 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index, adj_nbr_update_rewrite_internal(adj, IP_LOOKUP_NEXT_MIDCHAIN, adj_get_midchain_node(adj->ia_link), - adj->sub_type.midchain.tx_function_node, + tx_node, rewrite); } @@ -491,7 +498,7 @@ adj_nbr_midchain_stack (adj_index_t adj_index, ASSERT(IP_LOOKUP_NEXT_MIDCHAIN == adj->lookup_next_index); - dpo_stack_from_node(adj->sub_type.midchain.tx_function_node, + dpo_stack_from_node(adj_nbr_midchain_get_tx_node(adj), &adj->sub_type.midchain.next_dpo, next); } diff --git a/src/vnet/adj/adj_midchain.h b/src/vnet/adj/adj_midchain.h index ae414aea..27ca1d33 100644 --- a/src/vnet/adj/adj_midchain.h +++ b/src/vnet/adj/adj_midchain.h @@ -24,26 +24,6 @@ #include -/** - * @brief Flags controlling the midchain adjacency - */ -typedef enum adj_midchain_flag_t_ -{ - /** - * No flags - */ - ADJ_MIDCHAIN_FLAG_NONE = 0, - - /** - * Packets TX through the midchain do not increment the interface - * counters. This should be used when the adj is associated with an L2 - * interface and that L2 interface is in a bridege domain. In that case - * the packet will have traversed the interface's TX node, and hence have - * been counted, before it traverses ths midchain - */ - ADJ_MIDCHAIN_FLAG_NO_COUNT = (1 << 0), -} adj_midchain_flag_t; - /** * @brief * Convert an existing neighbour adjacency into a midchain @@ -60,7 +40,7 @@ typedef enum adj_midchain_flag_t_ */ extern void adj_nbr_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, - adj_midchain_flag_t flags, + adj_flags_t flags, u8 *rewrite); /** diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c index 072abd03..ddacb030 100644 --- a/src/vnet/adj/adj_nbr.c +++ b/src/vnet/adj/adj_nbr.c @@ -333,7 +333,7 @@ adj_nbr_update_rewrite (adj_index_t adj_index, */ void adj_nbr_update_rewrite_internal (ip_adjacency_t *adj, - u32 adj_next_index, + ip_lookup_next_t adj_next_index, u32 this_node, u32 next_node, u8 *rewrite) @@ -367,7 +367,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj, if (ADJ_INDEX_INVALID != walk_ai) { walk_adj = adj_get(walk_ai); - if (IP_ADJ_SYNC_WALK_ACTIVE & walk_adj->ia_flags) + if (ADJ_FLAG_SYNC_WALK_ACTIVE & walk_adj->ia_flags) { do_walk = 0; } @@ -376,7 +376,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj, /* * Prevent re-entrant walk of the same adj */ - walk_adj->ia_flags |= IP_ADJ_SYNC_WALK_ACTIVE; + walk_adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE; do_walk = 1; } } @@ -502,7 +502,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj, */ if (do_walk) { - walk_adj->ia_flags &= ~IP_ADJ_SYNC_WALK_ACTIVE; + walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE; } adj_unlock(adj_get_index(adj)); diff --git a/src/vnet/adj/rewrite.c b/src/vnet/adj/rewrite.c new file mode 100644 index 00000000..47fb74df --- /dev/null +++ b/src/vnet/adj/rewrite.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * rewrite.c: packet rewrite + * + * Copyright (c) 2008 Eliot Dresselhaus + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +void +vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0, + vnet_rewrite_data_t * rw0, + word n_left, uword most_likely_size) +{ + uword n_done = + round_pow2 (most_likely_size, sizeof (rw0[0])) / sizeof (rw0[0]); + + p0 -= n_done; + rw0 -= n_done; + + /* As we enter the cleanup loop, p0 and rw0 point to the last chunk written + by the fast path. Hence, the constant 1, which the + vnet_rewrite_copy_one macro renders as p0[-1] = rw0[-1]. */ + + while (n_left > 0) + { + vnet_rewrite_copy_one (p0, rw0, 1); + p0--; + rw0--; + n_left--; + } +} + +u8 * +format_vnet_rewrite (u8 * s, va_list * args) +{ + vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *); + u32 max_data_bytes = va_arg (*args, u32); + CLIB_UNUSED (uword indent) = va_arg (*args, u32); + vnet_main_t *vnm = vnet_get_main (); + + if (rw->sw_if_index != ~0) + { + vnet_sw_interface_t *si; + si = vnet_get_sw_interface_safe (vnm, rw->sw_if_index); + if (NULL != si) + s = format (s, "%U: ", format_vnet_sw_interface_name, vnm, si); + else + s = format (s, "DELETED:%d", rw->sw_if_index); + } + + /* Format rewrite string. */ + if (rw->data_bytes > 0) + + s = format (s, "%U", + format_hex_bytes, + rw->data + max_data_bytes - rw->data_bytes, rw->data_bytes); + + return s; +} + +u32 +vnet_tx_node_index_for_sw_interface (vnet_main_t * vnm, u32 sw_if_index) +{ + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + return (hw->output_node_index); +} + +void +vnet_rewrite_init (vnet_main_t * vnm, + u32 sw_if_index, + u32 this_node, u32 next_node, vnet_rewrite_header_t * rw) +{ + rw->sw_if_index = sw_if_index; + rw->next_index = vlib_node_add_next (vnm->vlib_main, this_node, next_node); + rw->max_l3_packet_bytes = + vnet_sw_interface_get_mtu (vnm, sw_if_index, VLIB_TX); +} + +void +vnet_rewrite_for_sw_interface (vnet_main_t * vnm, + vnet_link_t link_type, + u32 sw_if_index, + u32 node_index, + void *dst_address, + vnet_rewrite_header_t * rw, + u32 max_rewrite_bytes) +{ + + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + vnet_hw_interface_class_t *hc = + vnet_get_hw_interface_class (vnm, hw->hw_class_index); + u8 *rewrite = NULL; + + vnet_rewrite_init (vnm, sw_if_index, node_index, + vnet_tx_node_index_for_sw_interface (vnm, sw_if_index), + rw); + + ASSERT (hc->build_rewrite); + rewrite = hc->build_rewrite (vnm, sw_if_index, link_type, dst_address); + + ASSERT (vec_len (rewrite) < max_rewrite_bytes); + vnet_rewrite_set_data_internal (rw, max_rewrite_bytes, rewrite, + vec_len (rewrite)); + vec_free (rewrite); +} + +void +vnet_rewrite_for_tunnel (vnet_main_t * vnm, + u32 tx_sw_if_index, + u32 rewrite_node_index, + u32 post_rewrite_node_index, + vnet_rewrite_header_t * rw, + u8 * rewrite_data, u32 rewrite_length) +{ + ip_adjacency_t *adj = 0; + /* + * Installed into vnet_buffer(b)->sw_if_index[VLIB_TX] e.g. + * by ip4_rewrite_inline. If the post-rewrite node injects into + * ipX-forward, this will be interpreted as a FIB number. + */ + rw->sw_if_index = tx_sw_if_index; + rw->next_index = vlib_node_add_next (vnm->vlib_main, rewrite_node_index, + post_rewrite_node_index); + rw->max_l3_packet_bytes = (u16) ~ 0; /* we can't know at this point */ + + ASSERT (rewrite_length < sizeof (adj->rewrite_data)); + /* Leave room for ethernet + VLAN tag */ + vnet_rewrite_set_data_internal (rw, sizeof (adj->rewrite_data), + rewrite_data, rewrite_length); +} + +void +serialize_vnet_rewrite (serialize_main_t * m, va_list * va) +{ + vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *); + u32 max_data_bytes = va_arg (*va, u32); + u8 *p; + + serialize_integer (m, rw->sw_if_index, sizeof (rw->sw_if_index)); + serialize_integer (m, rw->data_bytes, sizeof (rw->data_bytes)); + serialize_integer (m, rw->max_l3_packet_bytes, + sizeof (rw->max_l3_packet_bytes)); + p = serialize_get (m, rw->data_bytes); + clib_memcpy (p, vnet_rewrite_get_data_internal (rw, max_data_bytes), + rw->data_bytes); +} + +void +unserialize_vnet_rewrite (serialize_main_t * m, va_list * va) +{ + vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *); + u32 max_data_bytes = va_arg (*va, u32); + u8 *p; + + /* It is up to user to fill these in. */ + rw->next_index = ~0; + + unserialize_integer (m, &rw->sw_if_index, sizeof (rw->sw_if_index)); + unserialize_integer (m, &rw->data_bytes, sizeof (rw->data_bytes)); + unserialize_integer (m, &rw->max_l3_packet_bytes, + sizeof (rw->max_l3_packet_bytes)); + p = unserialize_get (m, rw->data_bytes); + clib_memcpy (vnet_rewrite_get_data_internal (rw, max_data_bytes), p, + rw->data_bytes); +} + +u8 * +vnet_build_rewrite_for_sw_interface (vnet_main_t * vnm, + u32 sw_if_index, + vnet_link_t link_type, + const void *dst_address) +{ + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + vnet_hw_interface_class_t *hc = + vnet_get_hw_interface_class (vnm, hw->hw_class_index); + + ASSERT (hc->build_rewrite); + return (hc->build_rewrite (vnm, sw_if_index, link_type, dst_address)); +} + + +void +vnet_update_adjacency_for_sw_interface (vnet_main_t * vnm, + u32 sw_if_index, u32 ai) +{ + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + vnet_hw_interface_class_t *hc = + vnet_get_hw_interface_class (vnm, hw->hw_class_index); + + ASSERT (hc->update_adjacency); + hc->update_adjacency (vnm, sw_if_index, ai); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/adj/rewrite.h b/src/vnet/adj/rewrite.h new file mode 100644 index 00000000..1dea72f5 --- /dev/null +++ b/src/vnet/adj/rewrite.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * rewrite.h: packet rewrite + * + * Copyright (c) 2008 Eliot Dresselhaus + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef included_vnet_rewrite_h +#define included_vnet_rewrite_h + +#include +#include + +/* Consider using vector types for speed? */ +typedef uword vnet_rewrite_data_t; + +/** + * Flags associated with the rewrite/adjacency + */ +typedef enum vnet_rewrite_flags_t_ +{ + /** + * This adjacency/interface has output features configured + */ + VNET_REWRITE_HAS_FEATURES = (1 << 0), +} __attribute__ ((packed)) vnet_rewrite_flags_t; + +/* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + /* Interface to mark re-written packets with. */ + u32 sw_if_index; + + /* Next node to feed after packet rewrite is done. */ + u16 next_index; + + /* Number of bytes in rewrite data. */ + u16 data_bytes; + + /* Max packet size layer 3 (MTU) for output interface. + Used for MTU check after packet rewrite. */ + u16 max_l3_packet_bytes; + + /* Data-plane flags on the adjacency/rewrite */ + vnet_rewrite_flags_t flags; + + /* When dynamically writing a multicast destination L2 addresss + * this is the offset from the IP address at which to write in the + * IP->MAC address translation. + */ + u8 dst_mcast_offset; + + /* The mask to apply to the lower 4 bytes of the IP address before ORing + * into the destinaiton MAC address */ + u32 dst_mcast_mask; + + /* Rewrite string starting at end and going backwards. */ + u8 data[0]; +}) vnet_rewrite_header_t; +/* *INDENT-ON* */ + +/** + * At 16 bytes of rewrite herader we have enought space left for a IPv6 + * (40 bytes) + LISP-GPE (8 bytes) in the cache line + */ +STATIC_ASSERT (sizeof (vnet_rewrite_header_t) <= 16, + "Rewrite header too big"); + +/* + Helper macro for declaring rewrite string w/ given max-size. + + Typical usage: + typedef struct { + // + int a, b; + + // Total adjacency is 64 bytes. + vnet_rewrite_declare(64 - 2*sizeof(int)) rw; + } my_adjacency_t; +*/ +#define vnet_declare_rewrite(total_bytes) \ +struct { \ + vnet_rewrite_header_t rewrite_header; \ + \ + u8 rewrite_data[(total_bytes) - sizeof (vnet_rewrite_header_t)]; \ +} + +always_inline void +vnet_rewrite_clear_data_internal (vnet_rewrite_header_t * rw, int max_size) +{ + /* Sanity check values carefully for this memset operation */ + ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE)); + + rw->data_bytes = 0; + memset (rw->data, 0xfe, max_size); +} + +always_inline void +vnet_rewrite_set_data_internal (vnet_rewrite_header_t * rw, + int max_size, void *data, int data_bytes) +{ + /* Sanity check values carefully for this memset operation */ + ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE)); + ASSERT ((data_bytes >= 0) && (data_bytes < max_size)); + + rw->data_bytes = data_bytes; + clib_memcpy (rw->data + max_size - data_bytes, data, data_bytes); + memset (rw->data, 0xfe, max_size - data_bytes); +} + +#define vnet_rewrite_set_data(rw,data,data_bytes) \ + vnet_rewrite_set_data_internal (&((rw).rewrite_header), \ + sizeof ((rw).rewrite_data), \ + (data), \ + (data_bytes)) + +always_inline void * +vnet_rewrite_get_data_internal (vnet_rewrite_header_t * rw, int max_size) +{ + ASSERT (rw->data_bytes <= max_size); + return rw->data + max_size - rw->data_bytes; +} + +#define vnet_rewrite_get_data(rw) \ + vnet_rewrite_get_data_internal (&((rw).rewrite_header), sizeof ((rw).rewrite_data)) + +always_inline void +vnet_rewrite_copy_one (vnet_rewrite_data_t * p0, vnet_rewrite_data_t * rw0, + int i) +{ + p0[-i] = rw0[-i]; +} + +void vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0, + vnet_rewrite_data_t * rw0, + word n_left, uword most_likely_size); + +/* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + u64 a; + u32 b; + u16 c; +}) eh_copy_t; +/* *INDENT-ON* */ + +always_inline void +_vnet_rewrite_one_header (vnet_rewrite_header_t * h0, + void *packet0, int max_size, int most_likely_size) +{ + vnet_rewrite_data_t *p0 = packet0; + vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size); + word n_left0; + + /* 0xfefe => poisoned adjacency => crash */ + ASSERT (h0->data_bytes != 0xfefe); + + if (PREDICT_TRUE (h0->data_bytes == sizeof (eh_copy_t))) + { + eh_copy_t *s, *d; + s = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t)); + d = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t)); + clib_memcpy (d, s, sizeof (eh_copy_t)); + return; + } + + +#define _(i) \ + do { \ + if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \ + vnet_rewrite_copy_one (p0, rw0, (i)); \ + } while (0) + + _(4); + _(3); + _(2); + _(1); + +#undef _ + + n_left0 = (int) + (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1)) + / (int) sizeof (rw0[0]); + if (PREDICT_FALSE (n_left0 > 0)) + vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size); +} + +always_inline void +_vnet_rewrite_two_headers (vnet_rewrite_header_t * h0, + vnet_rewrite_header_t * h1, + void *packet0, + void *packet1, int max_size, int most_likely_size) +{ + vnet_rewrite_data_t *p0 = packet0; + vnet_rewrite_data_t *p1 = packet1; + vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size); + vnet_rewrite_data_t *rw1 = (vnet_rewrite_data_t *) (h1->data + max_size); + word n_left0, n_left1; + int slow_path; + + /* 0xfefe => poisoned adjacency => crash */ + ASSERT (h0->data_bytes != 0xfefe); + ASSERT (h1->data_bytes != 0xfefe); + + /* Arithmetic calculation: bytes0 == bytes1 == 14 */ + slow_path = h0->data_bytes ^ h1->data_bytes; + slow_path += h0->data_bytes ^ sizeof (eh_copy_t); + + if (PREDICT_TRUE (slow_path == 0)) + { + eh_copy_t *s0, *d0, *s1, *d1; + s0 = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t)); + d0 = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t)); + clib_memcpy (d0, s0, sizeof (eh_copy_t)); + s1 = (eh_copy_t *) (h1->data + max_size - sizeof (eh_copy_t)); + d1 = (eh_copy_t *) (((u8 *) packet1) - sizeof (eh_copy_t)); + clib_memcpy (d1, s1, sizeof (eh_copy_t)); + return; + } + +#define _(i) \ + do { \ + if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \ + { \ + vnet_rewrite_copy_one (p0, rw0, (i)); \ + vnet_rewrite_copy_one (p1, rw1, (i)); \ + } \ + } while (0) + + _(4); + _(3); + _(2); + _(1); + +#undef _ + + n_left0 = (int) + (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1)) + / (int) sizeof (rw0[0]); + n_left1 = (int) + (((int) h1->data_bytes - most_likely_size) + (sizeof (rw1[0]) - 1)) + / (int) sizeof (rw1[0]); + + if (PREDICT_FALSE (n_left0 > 0 || n_left1 > 0)) + { + vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size); + vnet_rewrite_copy_slow_path (p1, rw1, n_left1, most_likely_size); + } +} + +#define vnet_rewrite_one_header(rw0,p0,most_likely_size) \ + _vnet_rewrite_one_header (&((rw0).rewrite_header), (p0), \ + sizeof ((rw0).rewrite_data), \ + (most_likely_size)) + +#define vnet_rewrite_two_headers(rw0,rw1,p0,p1,most_likely_size) \ + _vnet_rewrite_two_headers (&((rw0).rewrite_header), &((rw1).rewrite_header), \ + (p0), (p1), \ + sizeof ((rw0).rewrite_data), \ + (most_likely_size)) + +always_inline void +_vnet_fixup_one_header (vnet_rewrite_header_t * h0, + u8 * addr, u32 addr_len, u8 * packet0) +{ + if (PREDICT_TRUE (h0->dst_mcast_mask)) + { + /* location to write to in the packet */ + u8 *p0 = packet0 - h0->dst_mcast_offset; + u32 *p1 = (u32 *) p0; + /* location to copy from in the L3 dest address */ + u32 *a0 = (u32 *) (addr + addr_len - sizeof (h0->dst_mcast_mask)); + + *p1 |= (*a0 & h0->dst_mcast_mask); + } +} + +#define vnet_fixup_one_header(rw0,addr,p0) \ + _vnet_fixup_one_header (&((rw0).rewrite_header), \ + (u8*)(addr), sizeof((*addr)), \ + (u8*)(p0)) + +#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST ((void *) 0) +/** Deprecated */ +void vnet_rewrite_for_sw_interface (struct vnet_main_t *vnm, + vnet_link_t packet_type, + u32 sw_if_index, + u32 node_index, + void *dst_address, + vnet_rewrite_header_t * rw, + u32 max_rewrite_bytes); + +u32 vnet_tx_node_index_for_sw_interface (struct vnet_main_t *vnm, + u32 sw_if_index); + +void vnet_rewrite_init (struct vnet_main_t *vnm, + u32 sw_if_index, + u32 this_node, + u32 next_node, vnet_rewrite_header_t * rw); + +u8 *vnet_build_rewrite_for_sw_interface (struct vnet_main_t *vnm, + u32 sw_if_index, + vnet_link_t packet_type, + const void *dst_address); +void vnet_update_adjacency_for_sw_interface (struct vnet_main_t *vnm, + u32 sw_if_index, u32 ai); + +format_function_t format_vnet_rewrite; + +serialize_function_t serialize_vnet_rewrite, unserialize_vnet_rewrite; + +#endif /* included_vnet_rewrite_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 09ecd0cc..ee757505 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -507,7 +507,6 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) case IP_LOOKUP_NEXT_PUNT: case IP_LOOKUP_NEXT_LOCAL: case IP_LOOKUP_NEXT_REWRITE: - case IP_LOOKUP_NEXT_LOAD_BALANCE: case IP_LOOKUP_NEXT_MIDCHAIN: case IP_LOOKUP_NEXT_ICMP_ERROR: case IP_LOOKUP_N_NEXT: diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c index 29d0f0fe..3d381388 100644 --- a/src/vnet/gre/gre.c +++ b/src/vnet/gre/gre.c @@ -242,8 +242,8 @@ gre_update_adj (vnet_main_t * vnm, { adj_nbr_midchain_update_rewrite (ai, gre_fixup, (VNET_LINK_ETHERNET == adj_get_link_type (ai) ? - ADJ_MIDCHAIN_FLAG_NO_COUNT : - ADJ_MIDCHAIN_FLAG_NONE), + ADJ_FLAG_MIDCHAIN_NO_COUNT : + ADJ_FLAG_NONE), gre_build_rewrite(vnm, sw_if_index, adj_get_link_type(ai), NULL)); diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index b1a03546..5d1fb6f8 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -557,7 +557,6 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) case IP_LOOKUP_NEXT_PUNT: case IP_LOOKUP_NEXT_LOCAL: case IP_LOOKUP_NEXT_REWRITE: - case IP_LOOKUP_NEXT_LOAD_BALANCE: case IP_LOOKUP_NEXT_MIDCHAIN: case IP_LOOKUP_NEXT_ICMP_ERROR: case IP_LOOKUP_N_NEXT: diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index dabfa012..95f36d41 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -188,13 +188,6 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip_sw_interface_add_del); void ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6) { - /* ensure that adjacency is cacheline aligned and sized */ - STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0, - "Cache line marker must be 1st element in struct"); - STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) == - CLIB_CACHE_LINE_BYTES, - "Data in cache line 0 is bigger than cache line size"); - /* Preallocate three "special" adjacencies */ lm->adjacency_heap = adj_pool; @@ -251,7 +244,8 @@ format_ip_flow_hash_config (u8 * s, va_list * args) u8 * format_ip_lookup_next (u8 * s, va_list * args) { - ip_lookup_next_t n = va_arg (*args, ip_lookup_next_t); + /* int promotion of ip_lookup_next_t */ + ip_lookup_next_t n = va_arg (*args, int); char *t = 0; switch (n) diff --git a/src/vnet/ip/lookup.h b/src/vnet/ip/lookup.h index f76ddb37..662a1cc0 100644 --- a/src/vnet/ip/lookup.h +++ b/src/vnet/ip/lookup.h @@ -53,93 +53,9 @@ #include #include #include +#include #include #include -#include - -/** @brief Common (IP4/IP6) next index stored in adjacency. */ -typedef enum -{ - /** Adjacency to drop this packet. */ - IP_LOOKUP_NEXT_DROP, - /** Adjacency to punt this packet. */ - IP_LOOKUP_NEXT_PUNT, - - /** This packet is for one of our own IP addresses. */ - IP_LOOKUP_NEXT_LOCAL, - - /** This packet matches an "incomplete adjacency" and packets - need to be passed to ARP to find rewrite string for - this destination. */ - IP_LOOKUP_NEXT_ARP, - - /** This packet matches an "interface route" and packets - need to be passed to ARP to find rewrite string for - this destination. */ - IP_LOOKUP_NEXT_GLEAN, - - /** This packet is to be rewritten and forwarded to the next - processing node. This is typically the output interface but - might be another node for further output processing. */ - IP_LOOKUP_NEXT_REWRITE, - - /** This packets follow a load-balance */ - IP_LOOKUP_NEXT_LOAD_BALANCE, - - /** This packets follow a mid-chain adjacency */ - IP_LOOKUP_NEXT_MIDCHAIN, - - /** This packets needs to go to ICMP error */ - IP_LOOKUP_NEXT_ICMP_ERROR, - - /** Multicast Adjacency. */ - IP_LOOKUP_NEXT_MCAST, - - IP_LOOKUP_N_NEXT, -} ip_lookup_next_t; - -typedef enum -{ - IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT, -} ip4_lookup_next_t; - -typedef enum -{ - /* Hop-by-hop header handling */ - IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT, - IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP, - IP6_LOOKUP_NEXT_POP_HOP_BY_HOP, - IP6_LOOKUP_N_NEXT, -} ip6_lookup_next_t; - -#define IP4_LOOKUP_NEXT_NODES { \ - [IP_LOOKUP_NEXT_DROP] = "ip4-drop", \ - [IP_LOOKUP_NEXT_PUNT] = "ip4-punt", \ - [IP_LOOKUP_NEXT_LOCAL] = "ip4-local", \ - [IP_LOOKUP_NEXT_ARP] = "ip4-arp", \ - [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \ - [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \ - [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \ - [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \ - [IP_LOOKUP_NEXT_LOAD_BALANCE] = "ip4-load-balance", \ - [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \ -} - -#define IP6_LOOKUP_NEXT_NODES { \ - [IP_LOOKUP_NEXT_DROP] = "ip6-drop", \ - [IP_LOOKUP_NEXT_PUNT] = "ip6-punt", \ - [IP_LOOKUP_NEXT_LOCAL] = "ip6-local", \ - [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \ - [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \ - [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \ - [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \ - [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \ - [IP_LOOKUP_NEXT_LOAD_BALANCE] = "ip6-load-balance", \ - [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error", \ - [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \ - [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \ - [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \ -} /** Flow hash configuration */ #define IP_FLOW_HASH_SRC_ADDR (1<<0) @@ -165,129 +81,6 @@ _(reverse, IP_FLOW_HASH_REVERSE_SRC_DST) */ typedef u32 flow_hash_config_t; -/** - * Forward delcartion - */ -struct ip_adjacency_t_; - -/** - * @brief A function type for post-rewrite fixups on midchain adjacency - */ -typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm, - struct ip_adjacency_t_ * adj, - vlib_buffer_t * b0); - -/** - * @brief Flags on an IP adjacency - */ -typedef enum ip_adjacency_flags_t_ -{ - /** - * Currently a sync walk is active. Used to prevent re-entrant walking - */ - IP_ADJ_SYNC_WALK_ACTIVE = (1 << 0), -} ip_adjacency_flags_t; - -/** @brief IP unicast adjacency. - @note cache aligned. -*/ -typedef struct ip_adjacency_t_ -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - - /** Number of adjecencies in block. Greater than 1 means multipath; - otherwise equal to 1. */ - u16 n_adj; - - /** Next hop after ip4-lookup. */ - union - { - ip_lookup_next_t lookup_next_index:16; - u16 lookup_next_index_as_int; - }; - - /** Interface address index for this local/arp adjacency. */ - u32 if_address_index; - - /* - * link/ether-type - */ - vnet_link_t ia_link; - u8 ia_nh_proto; - - union - { - /** - * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE - * - * neighbour adjacency sub-type; - */ - struct - { - ip46_address_t next_hop; - } nbr; - /** - * IP_LOOKUP_NEXT_MIDCHAIN - * - * A nbr adj that is also recursive. Think tunnels. - * A nbr adj can transition to be of type MDICHAIN - * so be sure to leave the two structs with the next_hop - * fields aligned. - */ - struct - { - /** - * The recursive next-hop - */ - ip46_address_t next_hop; - /** - * The node index of the tunnel's post rewrite/TX function. - */ - u32 tx_function_node; - /** - * The next DPO to use - */ - dpo_id_t next_dpo; - /** - * A function to perform the post-rewrite fixup - */ - adj_midchain_fixup_t fixup_func; - } midchain; - /** - * IP_LOOKUP_NEXT_GLEAN - * - * Glean the address to ARP for from the packet's destination - */ - struct - { - ip46_address_t receive_addr; - } glean; - } sub_type; - - CLIB_CACHE_LINE_ALIGN_MARK (cacheline1); - - /* Rewrite in second/third cache lines */ - vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE); - - /* - * member not accessed in the data plane are relgated to the - * remaining cachelines - */ - fib_node_t ia_node; - - /** - * Flags on the adjacency - */ - ip_adjacency_flags_t ia_flags; - -} ip_adjacency_t; - -STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0), - "IP adjacency cachline 0 is not offset"); -STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) == - CLIB_CACHE_LINE_BYTES), - "IP adjacency cachline 1 is more than one cachline size offset"); - /* An all zeros address */ extern const ip46_address_t zero_addr; diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c index 50662dd6..79b2a07f 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c +++ b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c @@ -361,8 +361,8 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) adj_nbr_midchain_update_rewrite (ai, lisp_gpe_fixup, (VNET_LINK_ETHERNET == linkt ? - ADJ_MIDCHAIN_FLAG_NO_COUNT : - ADJ_MIDCHAIN_FLAG_NONE), + ADJ_FLAG_MIDCHAIN_NO_COUNT : + ADJ_FLAG_NONE), lisp_gpe_tunnel_build_rewrite (lgt, ladj, lisp_gpe_adj_proto_from_vnet_link_type (linkt))); diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c index e488271d..ac6fdcdf 100644 --- a/src/vnet/mpls/mpls_tunnel.c +++ b/src/vnet/mpls/mpls_tunnel.c @@ -275,7 +275,7 @@ mpls_tunnel_update_adj (vnet_main_t * vnm, { adj_nbr_midchain_update_rewrite( ai, mpls_tunnel_fixup, - ADJ_MIDCHAIN_FLAG_NONE, + ADJ_FLAG_NONE, mpls_tunnel_build_rewrite(vnm, sw_if_index, adj_get_link_type(ai), NULL)); diff --git a/src/vnet/rewrite.c b/src/vnet/rewrite.c deleted file mode 100644 index 47fb74df..00000000 --- a/src/vnet/rewrite.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * rewrite.c: packet rewrite - * - * Copyright (c) 2008 Eliot Dresselhaus - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -void -vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0, - vnet_rewrite_data_t * rw0, - word n_left, uword most_likely_size) -{ - uword n_done = - round_pow2 (most_likely_size, sizeof (rw0[0])) / sizeof (rw0[0]); - - p0 -= n_done; - rw0 -= n_done; - - /* As we enter the cleanup loop, p0 and rw0 point to the last chunk written - by the fast path. Hence, the constant 1, which the - vnet_rewrite_copy_one macro renders as p0[-1] = rw0[-1]. */ - - while (n_left > 0) - { - vnet_rewrite_copy_one (p0, rw0, 1); - p0--; - rw0--; - n_left--; - } -} - -u8 * -format_vnet_rewrite (u8 * s, va_list * args) -{ - vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *); - u32 max_data_bytes = va_arg (*args, u32); - CLIB_UNUSED (uword indent) = va_arg (*args, u32); - vnet_main_t *vnm = vnet_get_main (); - - if (rw->sw_if_index != ~0) - { - vnet_sw_interface_t *si; - si = vnet_get_sw_interface_safe (vnm, rw->sw_if_index); - if (NULL != si) - s = format (s, "%U: ", format_vnet_sw_interface_name, vnm, si); - else - s = format (s, "DELETED:%d", rw->sw_if_index); - } - - /* Format rewrite string. */ - if (rw->data_bytes > 0) - - s = format (s, "%U", - format_hex_bytes, - rw->data + max_data_bytes - rw->data_bytes, rw->data_bytes); - - return s; -} - -u32 -vnet_tx_node_index_for_sw_interface (vnet_main_t * vnm, u32 sw_if_index) -{ - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - return (hw->output_node_index); -} - -void -vnet_rewrite_init (vnet_main_t * vnm, - u32 sw_if_index, - u32 this_node, u32 next_node, vnet_rewrite_header_t * rw) -{ - rw->sw_if_index = sw_if_index; - rw->next_index = vlib_node_add_next (vnm->vlib_main, this_node, next_node); - rw->max_l3_packet_bytes = - vnet_sw_interface_get_mtu (vnm, sw_if_index, VLIB_TX); -} - -void -vnet_rewrite_for_sw_interface (vnet_main_t * vnm, - vnet_link_t link_type, - u32 sw_if_index, - u32 node_index, - void *dst_address, - vnet_rewrite_header_t * rw, - u32 max_rewrite_bytes) -{ - - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - vnet_hw_interface_class_t *hc = - vnet_get_hw_interface_class (vnm, hw->hw_class_index); - u8 *rewrite = NULL; - - vnet_rewrite_init (vnm, sw_if_index, node_index, - vnet_tx_node_index_for_sw_interface (vnm, sw_if_index), - rw); - - ASSERT (hc->build_rewrite); - rewrite = hc->build_rewrite (vnm, sw_if_index, link_type, dst_address); - - ASSERT (vec_len (rewrite) < max_rewrite_bytes); - vnet_rewrite_set_data_internal (rw, max_rewrite_bytes, rewrite, - vec_len (rewrite)); - vec_free (rewrite); -} - -void -vnet_rewrite_for_tunnel (vnet_main_t * vnm, - u32 tx_sw_if_index, - u32 rewrite_node_index, - u32 post_rewrite_node_index, - vnet_rewrite_header_t * rw, - u8 * rewrite_data, u32 rewrite_length) -{ - ip_adjacency_t *adj = 0; - /* - * Installed into vnet_buffer(b)->sw_if_index[VLIB_TX] e.g. - * by ip4_rewrite_inline. If the post-rewrite node injects into - * ipX-forward, this will be interpreted as a FIB number. - */ - rw->sw_if_index = tx_sw_if_index; - rw->next_index = vlib_node_add_next (vnm->vlib_main, rewrite_node_index, - post_rewrite_node_index); - rw->max_l3_packet_bytes = (u16) ~ 0; /* we can't know at this point */ - - ASSERT (rewrite_length < sizeof (adj->rewrite_data)); - /* Leave room for ethernet + VLAN tag */ - vnet_rewrite_set_data_internal (rw, sizeof (adj->rewrite_data), - rewrite_data, rewrite_length); -} - -void -serialize_vnet_rewrite (serialize_main_t * m, va_list * va) -{ - vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *); - u32 max_data_bytes = va_arg (*va, u32); - u8 *p; - - serialize_integer (m, rw->sw_if_index, sizeof (rw->sw_if_index)); - serialize_integer (m, rw->data_bytes, sizeof (rw->data_bytes)); - serialize_integer (m, rw->max_l3_packet_bytes, - sizeof (rw->max_l3_packet_bytes)); - p = serialize_get (m, rw->data_bytes); - clib_memcpy (p, vnet_rewrite_get_data_internal (rw, max_data_bytes), - rw->data_bytes); -} - -void -unserialize_vnet_rewrite (serialize_main_t * m, va_list * va) -{ - vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *); - u32 max_data_bytes = va_arg (*va, u32); - u8 *p; - - /* It is up to user to fill these in. */ - rw->next_index = ~0; - - unserialize_integer (m, &rw->sw_if_index, sizeof (rw->sw_if_index)); - unserialize_integer (m, &rw->data_bytes, sizeof (rw->data_bytes)); - unserialize_integer (m, &rw->max_l3_packet_bytes, - sizeof (rw->max_l3_packet_bytes)); - p = unserialize_get (m, rw->data_bytes); - clib_memcpy (vnet_rewrite_get_data_internal (rw, max_data_bytes), p, - rw->data_bytes); -} - -u8 * -vnet_build_rewrite_for_sw_interface (vnet_main_t * vnm, - u32 sw_if_index, - vnet_link_t link_type, - const void *dst_address) -{ - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - vnet_hw_interface_class_t *hc = - vnet_get_hw_interface_class (vnm, hw->hw_class_index); - - ASSERT (hc->build_rewrite); - return (hc->build_rewrite (vnm, sw_if_index, link_type, dst_address)); -} - - -void -vnet_update_adjacency_for_sw_interface (vnet_main_t * vnm, - u32 sw_if_index, u32 ai) -{ - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - vnet_hw_interface_class_t *hc = - vnet_get_hw_interface_class (vnm, hw->hw_class_index); - - ASSERT (hc->update_adjacency); - hc->update_adjacency (vnm, sw_if_index, ai); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/rewrite.h b/src/vnet/rewrite.h deleted file mode 100644 index 1dea72f5..00000000 --- a/src/vnet/rewrite.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * rewrite.h: packet rewrite - * - * Copyright (c) 2008 Eliot Dresselhaus - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef included_vnet_rewrite_h -#define included_vnet_rewrite_h - -#include -#include - -/* Consider using vector types for speed? */ -typedef uword vnet_rewrite_data_t; - -/** - * Flags associated with the rewrite/adjacency - */ -typedef enum vnet_rewrite_flags_t_ -{ - /** - * This adjacency/interface has output features configured - */ - VNET_REWRITE_HAS_FEATURES = (1 << 0), -} __attribute__ ((packed)) vnet_rewrite_flags_t; - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - /* Interface to mark re-written packets with. */ - u32 sw_if_index; - - /* Next node to feed after packet rewrite is done. */ - u16 next_index; - - /* Number of bytes in rewrite data. */ - u16 data_bytes; - - /* Max packet size layer 3 (MTU) for output interface. - Used for MTU check after packet rewrite. */ - u16 max_l3_packet_bytes; - - /* Data-plane flags on the adjacency/rewrite */ - vnet_rewrite_flags_t flags; - - /* When dynamically writing a multicast destination L2 addresss - * this is the offset from the IP address at which to write in the - * IP->MAC address translation. - */ - u8 dst_mcast_offset; - - /* The mask to apply to the lower 4 bytes of the IP address before ORing - * into the destinaiton MAC address */ - u32 dst_mcast_mask; - - /* Rewrite string starting at end and going backwards. */ - u8 data[0]; -}) vnet_rewrite_header_t; -/* *INDENT-ON* */ - -/** - * At 16 bytes of rewrite herader we have enought space left for a IPv6 - * (40 bytes) + LISP-GPE (8 bytes) in the cache line - */ -STATIC_ASSERT (sizeof (vnet_rewrite_header_t) <= 16, - "Rewrite header too big"); - -/* - Helper macro for declaring rewrite string w/ given max-size. - - Typical usage: - typedef struct { - // - int a, b; - - // Total adjacency is 64 bytes. - vnet_rewrite_declare(64 - 2*sizeof(int)) rw; - } my_adjacency_t; -*/ -#define vnet_declare_rewrite(total_bytes) \ -struct { \ - vnet_rewrite_header_t rewrite_header; \ - \ - u8 rewrite_data[(total_bytes) - sizeof (vnet_rewrite_header_t)]; \ -} - -always_inline void -vnet_rewrite_clear_data_internal (vnet_rewrite_header_t * rw, int max_size) -{ - /* Sanity check values carefully for this memset operation */ - ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE)); - - rw->data_bytes = 0; - memset (rw->data, 0xfe, max_size); -} - -always_inline void -vnet_rewrite_set_data_internal (vnet_rewrite_header_t * rw, - int max_size, void *data, int data_bytes) -{ - /* Sanity check values carefully for this memset operation */ - ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE)); - ASSERT ((data_bytes >= 0) && (data_bytes < max_size)); - - rw->data_bytes = data_bytes; - clib_memcpy (rw->data + max_size - data_bytes, data, data_bytes); - memset (rw->data, 0xfe, max_size - data_bytes); -} - -#define vnet_rewrite_set_data(rw,data,data_bytes) \ - vnet_rewrite_set_data_internal (&((rw).rewrite_header), \ - sizeof ((rw).rewrite_data), \ - (data), \ - (data_bytes)) - -always_inline void * -vnet_rewrite_get_data_internal (vnet_rewrite_header_t * rw, int max_size) -{ - ASSERT (rw->data_bytes <= max_size); - return rw->data + max_size - rw->data_bytes; -} - -#define vnet_rewrite_get_data(rw) \ - vnet_rewrite_get_data_internal (&((rw).rewrite_header), sizeof ((rw).rewrite_data)) - -always_inline void -vnet_rewrite_copy_one (vnet_rewrite_data_t * p0, vnet_rewrite_data_t * rw0, - int i) -{ - p0[-i] = rw0[-i]; -} - -void vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0, - vnet_rewrite_data_t * rw0, - word n_left, uword most_likely_size); - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - u64 a; - u32 b; - u16 c; -}) eh_copy_t; -/* *INDENT-ON* */ - -always_inline void -_vnet_rewrite_one_header (vnet_rewrite_header_t * h0, - void *packet0, int max_size, int most_likely_size) -{ - vnet_rewrite_data_t *p0 = packet0; - vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size); - word n_left0; - - /* 0xfefe => poisoned adjacency => crash */ - ASSERT (h0->data_bytes != 0xfefe); - - if (PREDICT_TRUE (h0->data_bytes == sizeof (eh_copy_t))) - { - eh_copy_t *s, *d; - s = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t)); - d = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t)); - clib_memcpy (d, s, sizeof (eh_copy_t)); - return; - } - - -#define _(i) \ - do { \ - if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \ - vnet_rewrite_copy_one (p0, rw0, (i)); \ - } while (0) - - _(4); - _(3); - _(2); - _(1); - -#undef _ - - n_left0 = (int) - (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1)) - / (int) sizeof (rw0[0]); - if (PREDICT_FALSE (n_left0 > 0)) - vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size); -} - -always_inline void -_vnet_rewrite_two_headers (vnet_rewrite_header_t * h0, - vnet_rewrite_header_t * h1, - void *packet0, - void *packet1, int max_size, int most_likely_size) -{ - vnet_rewrite_data_t *p0 = packet0; - vnet_rewrite_data_t *p1 = packet1; - vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size); - vnet_rewrite_data_t *rw1 = (vnet_rewrite_data_t *) (h1->data + max_size); - word n_left0, n_left1; - int slow_path; - - /* 0xfefe => poisoned adjacency => crash */ - ASSERT (h0->data_bytes != 0xfefe); - ASSERT (h1->data_bytes != 0xfefe); - - /* Arithmetic calculation: bytes0 == bytes1 == 14 */ - slow_path = h0->data_bytes ^ h1->data_bytes; - slow_path += h0->data_bytes ^ sizeof (eh_copy_t); - - if (PREDICT_TRUE (slow_path == 0)) - { - eh_copy_t *s0, *d0, *s1, *d1; - s0 = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t)); - d0 = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t)); - clib_memcpy (d0, s0, sizeof (eh_copy_t)); - s1 = (eh_copy_t *) (h1->data + max_size - sizeof (eh_copy_t)); - d1 = (eh_copy_t *) (((u8 *) packet1) - sizeof (eh_copy_t)); - clib_memcpy (d1, s1, sizeof (eh_copy_t)); - return; - } - -#define _(i) \ - do { \ - if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \ - { \ - vnet_rewrite_copy_one (p0, rw0, (i)); \ - vnet_rewrite_copy_one (p1, rw1, (i)); \ - } \ - } while (0) - - _(4); - _(3); - _(2); - _(1); - -#undef _ - - n_left0 = (int) - (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1)) - / (int) sizeof (rw0[0]); - n_left1 = (int) - (((int) h1->data_bytes - most_likely_size) + (sizeof (rw1[0]) - 1)) - / (int) sizeof (rw1[0]); - - if (PREDICT_FALSE (n_left0 > 0 || n_left1 > 0)) - { - vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size); - vnet_rewrite_copy_slow_path (p1, rw1, n_left1, most_likely_size); - } -} - -#define vnet_rewrite_one_header(rw0,p0,most_likely_size) \ - _vnet_rewrite_one_header (&((rw0).rewrite_header), (p0), \ - sizeof ((rw0).rewrite_data), \ - (most_likely_size)) - -#define vnet_rewrite_two_headers(rw0,rw1,p0,p1,most_likely_size) \ - _vnet_rewrite_two_headers (&((rw0).rewrite_header), &((rw1).rewrite_header), \ - (p0), (p1), \ - sizeof ((rw0).rewrite_data), \ - (most_likely_size)) - -always_inline void -_vnet_fixup_one_header (vnet_rewrite_header_t * h0, - u8 * addr, u32 addr_len, u8 * packet0) -{ - if (PREDICT_TRUE (h0->dst_mcast_mask)) - { - /* location to write to in the packet */ - u8 *p0 = packet0 - h0->dst_mcast_offset; - u32 *p1 = (u32 *) p0; - /* location to copy from in the L3 dest address */ - u32 *a0 = (u32 *) (addr + addr_len - sizeof (h0->dst_mcast_mask)); - - *p1 |= (*a0 & h0->dst_mcast_mask); - } -} - -#define vnet_fixup_one_header(rw0,addr,p0) \ - _vnet_fixup_one_header (&((rw0).rewrite_header), \ - (u8*)(addr), sizeof((*addr)), \ - (u8*)(p0)) - -#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST ((void *) 0) -/** Deprecated */ -void vnet_rewrite_for_sw_interface (struct vnet_main_t *vnm, - vnet_link_t packet_type, - u32 sw_if_index, - u32 node_index, - void *dst_address, - vnet_rewrite_header_t * rw, - u32 max_rewrite_bytes); - -u32 vnet_tx_node_index_for_sw_interface (struct vnet_main_t *vnm, - u32 sw_if_index); - -void vnet_rewrite_init (struct vnet_main_t *vnm, - u32 sw_if_index, - u32 this_node, - u32 next_node, vnet_rewrite_header_t * rw); - -u8 *vnet_build_rewrite_for_sw_interface (struct vnet_main_t *vnm, - u32 sw_if_index, - vnet_link_t packet_type, - const void *dst_address); -void vnet_update_adjacency_for_sw_interface (struct vnet_main_t *vnm, - u32 sw_if_index, u32 ai); - -format_function_t format_vnet_rewrite; - -serialize_function_t serialize_vnet_rewrite, unserialize_vnet_rewrite; - -#endif /* included_vnet_rewrite_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ -- cgit 1.2.3-korg From 63d5bae6401049debadfa9fcc3f18d8118b80441 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Tue, 4 Apr 2017 01:28:26 +0200 Subject: Fix issue with gre protocol registration when running multithreaded Change-Id: Ic5bd7da08f8a46b548d56516e4633f0b8badf2a1 Signed-off-by: Damjan Marion --- src/vnet/gre/gre.h | 4 ++++ src/vnet/gre/node.c | 50 +++++++++++--------------------------------------- 2 files changed, 15 insertions(+), 39 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/vnet/gre/gre.h b/src/vnet/gre/gre.h index b6544b9b..788cba27 100644 --- a/src/vnet/gre/gre.h +++ b/src/vnet/gre/gre.h @@ -159,6 +159,10 @@ typedef struct { */ u32 * tunnel_index_by_sw_if_index; + /* Sparse vector mapping gre protocol in network byte order + to next index. */ + u16 * next_by_protocol; + /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; diff --git a/src/vnet/gre/node.c b/src/vnet/gre/node.c index dd16db5e..5926e83d 100644 --- a/src/vnet/gre/node.c +++ b/src/vnet/gre/node.c @@ -56,19 +56,12 @@ u8 * format_gre_rx_trace (u8 * s, va_list * args) return s; } -typedef struct { - /* Sparse vector mapping gre protocol in network byte order - to next index. */ - u16 * next_by_protocol; -} gre_input_runtime_t; - static uword gre_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { gre_main_t * gm = &gre_main; - gre_input_runtime_t * rt = (void *) node->runtime_data; __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next; u64 cached_tunnel_key = (u64) ~0; u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0; @@ -144,10 +137,10 @@ gre_input (vlib_main_t * vm, /* Index sparse array with network byte order. */ protocol0 = h0->protocol; protocol1 = h1->protocol; - sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1, + sparse_vec_index2 (gm->next_by_protocol, protocol0, protocol1, &i0, &i1); - next0 = vec_elt(rt->next_by_protocol, i0); - next1 = vec_elt(rt->next_by_protocol, i1); + next0 = vec_elt(gm->next_by_protocol, i0); + next1 = vec_elt(gm->next_by_protocol, i1); b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; b1->error = node->errors[i1 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; @@ -319,8 +312,8 @@ drop1: h0 = vlib_buffer_get_current (b0); - i0 = sparse_vec_index (rt->next_by_protocol, h0->protocol); - next0 = vec_elt(rt->next_by_protocol, i0); + i0 = sparse_vec_index (gm->next_by_protocol, h0->protocol); + next0 = vec_elt(gm->next_by_protocol, i0); b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX @@ -422,8 +415,6 @@ VLIB_REGISTER_NODE (gre_input_node) = { /* Takes a vector of packets. */ .vector_size = sizeof (u32), - .runtime_data_bytes = sizeof (gre_input_runtime_t), - .n_errors = GRE_N_ERROR, .error_strings = gre_error_strings, @@ -463,13 +454,9 @@ gre_register_input_protocol (vlib_main_t * vm, node_index); /* Setup gre protocol -> next index sparse vector mapping. */ - foreach_vlib_main ({ - gre_input_runtime_t * rt; - rt = vlib_node_get_runtime_data (this_vlib_main, gre_input_node.index); - n = sparse_vec_validate (rt->next_by_protocol, - clib_host_to_net_u16 (protocol)); - n[0] = pi->next_index; - }); + n = sparse_vec_validate (em->next_by_protocol, + clib_host_to_net_u16 (protocol)); + n[0] = pi->next_index; } static void @@ -485,7 +472,7 @@ gre_setup_node (vlib_main_t * vm, u32 node_index) static clib_error_t * gre_input_init (vlib_main_t * vm) { - gre_input_runtime_t * rt; + gre_main_t * gm = &gre_main; vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input; { @@ -497,10 +484,8 @@ static clib_error_t * gre_input_init (vlib_main_t * vm) gre_setup_node (vm, gre_input_node.index); - rt = vlib_node_get_runtime_data (vm, gre_input_node.index); - - rt->next_by_protocol = sparse_vec_new - (/* elt bytes */ sizeof (rt->next_by_protocol[0]), + gm->next_by_protocol = sparse_vec_new + (/* elt bytes */ sizeof (gm->next_by_protocol[0]), /* bits in index */ BITS (((gre_header_t *) 0)->protocol)); /* These could be moved to the supported protocol input node defn's */ @@ -532,16 +517,3 @@ static clib_error_t * gre_input_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (gre_input_init); -static clib_error_t * gre_input_worker_init (vlib_main_t * vm) -{ - gre_input_runtime_t * rt; - - rt = vlib_node_get_runtime_data (vm, gre_input_node.index); - - rt->next_by_protocol = sparse_vec_new - (/* elt bytes */ sizeof (rt->next_by_protocol[0]), - /* bits in index */ BITS (((gre_header_t *) 0)->protocol)); - return 0; -} - -VLIB_WORKER_INIT_FUNCTION (gre_input_worker_init); -- cgit 1.2.3-korg From 7eac916e1b00d6a3393a09925e1634d71bf30568 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Fri, 30 Sep 2016 15:47:03 +0100 Subject: GRE over IPv6 Refactors the GRE node to work with both IPv4 and IPv6 transports. Note that this changes the binary configuration API to support both address families; each address uses the same memory for either address type and a flag to indicate which is in use. The CLI and VAT syntax remains unchanged; the code detects whether an IPv4 or an IPv6 address was given. Configuration examples: IPv4 CLI: create gre tunnel src 192.168.1.1 dst 192.168.1.2 IPv6 CLI: create gre tunnel src 2620:124:9000::1 dst 2620:124:9000::2 IPv4 VAT: gre_add_del_tunnel src 192.168.1.1 dst 192.168.1.2 IPv6 VAT: gre_add_del_tunnel src 2620:124:9000::1 dst 2620:124:9000::2 Change-Id: Ica8ee775dc101047fb8cd41617ddc8fafc2741b0 Signed-off-by: Ciara Loftus --- src/vat/api_format.c | 78 +++++++++-- src/vnet/gre/gre.c | 110 ++++++++++++---- src/vnet/gre/gre.h | 30 +++-- src/vnet/gre/gre_api.c | 44 +++++-- src/vnet/gre/interface.c | 194 ++++++++++++++++++++-------- src/vnet/gre/node.c | 320 ++++++++++++++++++++++++++++++++++++---------- src/vnet/ipsec-gre/node.c | 24 ++-- test/test_gre.py | 149 ++++++++++++++++++++- test/vpp_gre_interface.py | 35 +++++ 9 files changed, 787 insertions(+), 197 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 06884eb1..090d990b 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -11018,21 +11018,45 @@ api_gre_add_del_tunnel (vat_main_t * vam) unformat_input_t *line_input = vam->input; vl_api_gre_add_del_tunnel_t *mp; ip4_address_t src4, dst4; + ip6_address_t src6, dst6; u8 is_add = 1; + u8 ipv4_set = 0; + u8 ipv6_set = 0; u8 teb = 0; u8 src_set = 0; u8 dst_set = 0; u32 outer_fib_id = 0; int ret; + memset (&src4, 0, sizeof src4); + memset (&dst4, 0, sizeof dst4); + memset (&src6, 0, sizeof src6); + memset (&dst6, 0, sizeof dst6); + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "del")) is_add = 0; else if (unformat (line_input, "src %U", unformat_ip4_address, &src4)) - src_set = 1; + { + src_set = 1; + ipv4_set = 1; + } else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst4)) - dst_set = 1; + { + dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "src %U", unformat_ip6_address, &src6)) + { + src_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst6)) + { + dst_set = 1; + ipv6_set = 1; + } else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id)) ; else if (unformat (line_input, "teb")) @@ -11054,15 +11078,29 @@ api_gre_add_del_tunnel (vat_main_t * vam) errmsg ("tunnel dst address not specified"); return -99; } + if (ipv4_set && ipv6_set) + { + errmsg ("both IPv4 and IPv6 addresses specified"); + return -99; + } M (GRE_ADD_DEL_TUNNEL, mp); - clib_memcpy (&mp->src_address, &src4, sizeof (src4)); - clib_memcpy (&mp->dst_address, &dst4, sizeof (dst4)); + if (ipv4_set) + { + clib_memcpy (&mp->src_address, &src4, 4); + clib_memcpy (&mp->dst_address, &dst4, 4); + } + else + { + clib_memcpy (&mp->src_address, &src6, 16); + clib_memcpy (&mp->dst_address, &dst6, 16); + } mp->outer_fib_id = ntohl (outer_fib_id); mp->is_add = is_add; mp->teb = teb; + mp->is_ipv6 = ipv6_set; S (mp); W (ret); @@ -11073,11 +11111,13 @@ static void vl_api_gre_tunnel_details_t_handler (vl_api_gre_tunnel_details_t * mp) { vat_main_t *vam = &vat_main; + ip46_address_t src = to_ip46 (mp->is_ipv6, mp->src_address); + ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->dst_address); - print (vam->ofp, "%11d%15U%15U%6d%14d", + print (vam->ofp, "%11d%24U%24U%6d%14d", ntohl (mp->sw_if_index), - format_ip4_address, &mp->src_address, - format_ip4_address, &mp->dst_address, + format_ip46_address, &src, IP46_TYPE_ANY, + format_ip46_address, &dst, IP46_TYPE_ANY, mp->teb, ntohl (mp->outer_fib_id)); } @@ -11087,6 +11127,7 @@ static void vl_api_gre_tunnel_details_t_handler_json vat_main_t *vam = &vat_main; vat_json_node_t *node = NULL; struct in_addr ip4; + struct in6_addr ip6; if (VAT_JSON_ARRAY != vam->json_tree.type) { @@ -11097,12 +11138,23 @@ static void vl_api_gre_tunnel_details_t_handler_json vat_json_init_object (node); vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); - clib_memcpy (&ip4, &mp->src_address, sizeof (ip4)); - vat_json_object_add_ip4 (node, "src_address", ip4); - clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4)); - vat_json_object_add_ip4 (node, "dst_address", ip4); + if (!mp->is_ipv6) + { + clib_memcpy (&ip4, &mp->src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "dst_address", ip4); + } + else + { + clib_memcpy (&ip6, &mp->src_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "src_address", ip6); + clib_memcpy (&ip6, &mp->dst_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "dst_address", ip6); + } vat_json_object_add_uint (node, "teb", mp->teb); vat_json_object_add_uint (node, "outer_fib_id", ntohl (mp->outer_fib_id)); + vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6); } static int @@ -11131,7 +11183,7 @@ api_gre_tunnel_dump (vat_main_t * vam) if (!vam->json_output) { - print (vam->ofp, "%11s%15s%15s%6s%14s", + print (vam->ofp, "%11s%24s%24s%6s%14s", "sw_if_index", "src_address", "dst_address", "teb", "outer_fib_id"); } @@ -18612,7 +18664,7 @@ _(vxlan_add_del_tunnel, \ "vni [encap-vrf-id ] [decap-next ] [del]") \ _(vxlan_tunnel_dump, "[ | sw_if_index ]") \ _(gre_add_del_tunnel, \ - "src dst [outer-fib-id ] [teb] [del]\n") \ + "src dst [outer-fib-id ] [teb] [del]\n") \ _(gre_tunnel_dump, "[ | sw_if_index ]") \ _(l2_fib_clear_table, "") \ _(l2_interface_efp_filter, "sw_if_index enable | disable") \ diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c index 3d381388..a153c3c5 100644 --- a/src/vnet/gre/gre.c +++ b/src/vnet/gre/gre.c @@ -28,6 +28,13 @@ typedef struct { }; } ip4_and_gre_union_t; +typedef struct { + union { + ip6_and_gre_header_t ip6_and_gre; + u64 as_u64[3]; + }; +} ip6_and_gre_union_t; + /* Packet trace structure */ typedef struct { @@ -37,9 +44,9 @@ typedef struct { /* pkt length */ u32 length; - /* tunnel ip4 addresses */ - ip4_address_t src; - ip4_address_t dst; + /* tunnel ip addresses */ + ip46_address_t src; + ip46_address_t dst; } gre_tx_trace_t; u8 * format_gre_tx_trace (u8 * s, va_list * args) @@ -50,8 +57,8 @@ u8 * format_gre_tx_trace (u8 * s, va_list * args) s = format (s, "GRE: tunnel %d len %d src %U dst %U", t->tunnel_id, clib_net_to_host_u16 (t->length), - format_ip4_address, &t->src.as_u8, - format_ip4_address, &t->dst.as_u8); + format_ip46_address, &t->src, IP46_TYPE_ANY, + format_ip46_address, &t->dst, IP46_TYPE_ANY); return s; } @@ -192,10 +199,12 @@ gre_build_rewrite (vnet_main_t * vnm, const void *dst_address) { gre_main_t * gm = &gre_main; - ip4_and_gre_header_t * h; + ip4_and_gre_header_t * h4; + ip6_and_gre_header_t * h6; u8* rewrite = NULL; gre_tunnel_t *t; u32 ti; + u8 is_ipv6; ti = gm->tunnel_index_by_sw_if_index[sw_if_index]; @@ -205,23 +214,45 @@ gre_build_rewrite (vnet_main_t * vnm, t = pool_elt_at_index(gm->tunnels, ti); - vec_validate(rewrite, sizeof(*h)-1); - h = (ip4_and_gre_header_t*)rewrite; - h->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type)); + is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; - h->ip4.ip_version_and_header_length = 0x45; - h->ip4.ttl = 254; - h->ip4.protocol = IP_PROTOCOL_GRE; - /* fixup ip4 header length and checksum after-the-fact */ - h->ip4.src_address.as_u32 = t->tunnel_src.as_u32; - h->ip4.dst_address.as_u32 = t->tunnel_dst.as_u32; - h->ip4.checksum = ip4_header_checksum (&h->ip4); + if (!is_ipv6) + { + vec_validate(rewrite, sizeof(*h4)-1); + h4 = (ip4_and_gre_header_t*)rewrite; + h4->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type)); + + h4->ip4.ip_version_and_header_length = 0x45; + h4->ip4.ttl = 254; + h4->ip4.protocol = IP_PROTOCOL_GRE; + /* fixup ip4 header length and checksum after-the-fact */ + h4->ip4.src_address.as_u32 = t->tunnel_src.ip4.as_u32; + h4->ip4.dst_address.as_u32 = t->tunnel_dst.fp_addr.ip4.as_u32; + h4->ip4.checksum = ip4_header_checksum (&h4->ip4); + } + else + { + vec_validate(rewrite, sizeof(*h6)-1); + h6 = (ip6_and_gre_header_t*)rewrite; + h6->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type)); + + h6->ip6.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32(6 << 28); + h6->ip6.hop_limit = 255; + h6->ip6.protocol = IP_PROTOCOL_GRE; + /* fixup ip6 header length and checksum after-the-fact */ + h6->ip6.src_address.as_u64[0] = t->tunnel_src.ip6.as_u64[0]; + h6->ip6.src_address.as_u64[1] = t->tunnel_src.ip6.as_u64[1]; + h6->ip6.dst_address.as_u64[0] = t->tunnel_dst.fp_addr.ip6.as_u64[0]; + h6->ip6.dst_address.as_u64[1] = t->tunnel_dst.fp_addr.ip6.as_u64[1]; + } return (rewrite); } +#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40 + void -gre_fixup (vlib_main_t *vm, +gre4_fixup (vlib_main_t *vm, ip_adjacency_t *adj, vlib_buffer_t *b0) { @@ -235,12 +266,37 @@ gre_fixup (vlib_main_t *vm, ip0->checksum = ip4_header_checksum (ip0); } +void +gre6_fixup (vlib_main_t *vm, + ip_adjacency_t *adj, + vlib_buffer_t *b0) +{ + ip6_header_t * ip0; + + ip0 = vlib_buffer_get_current (b0); + + /* Fixup the payload length field in the GRE tunnel encap that was applied + * at the midchain node */ + ip0->payload_length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)) + - sizeof(*ip0); +} + void gre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) { - adj_nbr_midchain_update_rewrite (ai, gre_fixup, + gre_main_t * gm = &gre_main; + gre_tunnel_t *t; + u32 ti; + u8 is_ipv6; + + ti = gm->tunnel_index_by_sw_if_index[sw_if_index]; + t = pool_elt_at_index(gm->tunnels, ti); + is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; + + adj_nbr_midchain_update_rewrite (ai, !is_ipv6 ? gre4_fixup : gre6_fixup, (VNET_LINK_ETHERNET == adj_get_link_type (ai) ? ADJ_FLAG_MIDCHAIN_NO_COUNT : ADJ_FLAG_NONE), @@ -264,6 +320,7 @@ gre_interface_tx_inline (vlib_main_t * vm, u32 * from, * to_next, n_left_from, n_left_to_next; vnet_interface_output_runtime_t * rd = (void *) node->runtime_data; const gre_tunnel_t *gt = pool_elt_at_index (gm->tunnels, rd->dev_instance); + u8 is_ipv6 = gt->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; /* Vector of buffer / pkt indices we're supposed to process */ from = vlib_frame_vector_args (frame); @@ -303,10 +360,10 @@ gre_interface_tx_inline (vlib_main_t * vm, { gre_tx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->tunnel_id = gt - gm->tunnels; - tr->length = vlib_buffer_length_in_chain (vm, b0); - tr->src.as_u32 = gt->tunnel_src.as_u32; - tr->dst.as_u32 = gt->tunnel_src.as_u32; + tr->tunnel_id = gt - gm->tunnels; + tr->src = gt->tunnel_src; + tr->dst = gt->tunnel_src; + tr->length = vlib_buffer_length_in_chain (vm, b0); } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, @@ -317,7 +374,8 @@ gre_interface_tx_inline (vlib_main_t * vm, vlib_put_next_frame (vm, node, next_index, n_left_to_next); } - vlib_node_increment_counter (vm, gre_input_node.index, + vlib_node_increment_counter (vm, !is_ipv6 ? gre4_input_node.index : + gre6_input_node.index, GRE_ERROR_PKTS_ENCAP, frame->n_vectors); return frame->n_vectors; @@ -434,6 +492,9 @@ static clib_error_t * gre_init (vlib_main_t * vm) if ((error = vlib_call_init_function (vm, ip4_lookup_init))) return error; + if ((error = vlib_call_init_function (vm, ip6_lookup_init))) + return error; + /* Set up the ip packet generator */ pi = ip_get_protocol_info (im, IP_PROTOCOL_GRE); pi->format_header = format_gre_header; @@ -441,7 +502,8 @@ static clib_error_t * gre_init (vlib_main_t * vm) gm->protocol_info_by_name = hash_create_string (0, sizeof (uword)); gm->protocol_info_by_protocol = hash_create (0, sizeof (uword)); - gm->tunnel_by_key = hash_create (0, sizeof (uword)); + gm->tunnel_by_key4 = hash_create (0, sizeof (uword)); + gm->tunnel_by_key6 = hash_create_mem (0, sizeof(u64[4]), sizeof (uword)); #define _(n,s) add_protocol (gm, GRE_PROTOCOL_##s, #s); foreach_gre_protocol diff --git a/src/vnet/gre/gre.h b/src/vnet/gre/gre.h index 788cba27..ad3e025a 100644 --- a/src/vnet/gre/gre.h +++ b/src/vnet/gre/gre.h @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include #include @@ -87,11 +85,11 @@ typedef struct { /** * The tunnel's source/local address */ - ip4_address_t tunnel_src; + ip46_address_t tunnel_src; /** * The tunnel's destination/remote address */ - ip4_address_t tunnel_dst; + fib_prefix_t tunnel_dst; /** * The FIB in which the src.dst address are present */ @@ -142,10 +140,16 @@ typedef struct { * Hash tables mapping name/protocol to protocol info index. */ uword * protocol_info_by_name, * protocol_info_by_protocol; + /** - * Hash mapping src/dst addr pair to tunnel + * Hash mapping ipv4 src/dst addr pair to tunnel */ - uword * tunnel_by_key; + uword * tunnel_by_key4; + + /** + * Hash mapping ipv6 src/dst addr pair to tunnel + */ + uword * tunnel_by_key6; /** * Free vlib hw_if_indices. @@ -176,6 +180,14 @@ typedef CLIB_PACKED (struct { gre_header_t gre; }) ip4_and_gre_header_t; +/** + * @brief IPv6 and GRE header. + */ +typedef CLIB_PACKED (struct { + ip6_header_t ip6; + gre_header_t gre; +}) ip6_and_gre_header_t; + always_inline gre_protocol_info_t * gre_get_protocol_info (gre_main_t * em, gre_protocol_t protocol) { @@ -204,7 +216,8 @@ format_function_t format_gre_protocol; format_function_t format_gre_header; format_function_t format_gre_header_with_length; -extern vlib_node_registration_t gre_input_node; +extern vlib_node_registration_t gre4_input_node; +extern vlib_node_registration_t gre6_input_node; extern vnet_device_class_t gre_device_class; extern vnet_device_class_t gre_device_teb_class; @@ -228,7 +241,8 @@ gre_register_input_protocol (vlib_main_t * vm, typedef struct { u8 is_add; - ip4_address_t src, dst; + ip46_address_t src, dst; + u8 is_ipv6; u32 outer_fib_id; u8 teb; } vnet_gre_add_del_tunnel_args_t; diff --git a/src/vnet/gre/gre_api.c b/src/vnet/gre/gre_api.c index 333838c0..ceeb1d4c 100644 --- a/src/vnet/gre/gre_api.c +++ b/src/vnet/gre/gre_api.c @@ -55,17 +55,17 @@ static void vl_api_gre_add_del_tunnel_t_handler int rv = 0; vnet_gre_add_del_tunnel_args_t _a, *a = &_a; u32 outer_fib_id; - uword *p; - ip4_main_t *im = &ip4_main; + u32 p; u32 sw_if_index = ~0; - p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id)); - if (!p) + p = fib_table_find (!mp->is_ipv6 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6, + ntohl (mp->outer_fib_id)); + if (p == ~0) { rv = VNET_API_ERROR_NO_SUCH_FIB; goto out; } - outer_fib_id = p[0]; + outer_fib_id = p; /* Check src & dst are different */ if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) || @@ -78,10 +78,19 @@ static void vl_api_gre_add_del_tunnel_t_handler a->is_add = mp->is_add; a->teb = mp->teb; + a->is_ipv6 = mp->is_ipv6; /* ip addresses sent in network byte order */ - clib_memcpy (&(a->src), mp->src_address, 4); - clib_memcpy (&(a->dst), mp->dst_address, 4); + if (!mp->is_ipv6) + { + clib_memcpy (&(a->src.ip4), mp->src_address, 4); + clib_memcpy (&(a->dst.ip4), mp->dst_address, 4); + } + else + { + clib_memcpy (&(a->src.ip6), mp->src_address, 16); + clib_memcpy (&(a->dst.ip6), mp->dst_address, 16); + } a->outer_fib_id = outer_fib_id; rv = vnet_gre_add_del_tunnel (a, &sw_if_index); @@ -99,17 +108,30 @@ static void send_gre_tunnel_details (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) { vl_api_gre_tunnel_details_t *rmp; - ip4_main_t *im = &ip4_main; + u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; + fib_table_t *ft; rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS); - clib_memcpy (rmp->src_address, &(t->tunnel_src), 4); - clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4); - rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id); + if (!is_ipv6) + { + clib_memcpy (rmp->src_address, &(t->tunnel_src.ip4.as_u8), 4); + clib_memcpy (rmp->dst_address, &(t->tunnel_dst.fp_addr.ip4.as_u8), 4); + ft = fib_table_get (t->outer_fib_index, FIB_PROTOCOL_IP4); + rmp->outer_fib_id = ft->ft_table_id; + } + else + { + clib_memcpy (rmp->src_address, &(t->tunnel_src.ip6.as_u8), 16); + clib_memcpy (rmp->dst_address, &(t->tunnel_dst.fp_addr.ip6.as_u8), 16); + ft = fib_table_get (t->outer_fib_index, FIB_PROTOCOL_IP6); + rmp->outer_fib_id = ft->ft_table_id; + } rmp->teb = (GRE_TUNNEL_TYPE_TEB == t->type); rmp->sw_if_index = htonl (t->sw_if_index); rmp->context = context; + rmp->is_ipv6 = is_ipv6; vl_msg_api_send_shmem (q, (u8 *) & rmp); } diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index d4476ac4..91a3899f 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,7 @@ static const char *gre_tunnel_type_names[] = GRE_TUNNEL_TYPE_NAMES; static inline u64 -gre_mk_key (const ip4_address_t *src, +gre4_mk_key (const ip4_address_t *src, const ip4_address_t *dst, u32 out_fib_index) { @@ -48,30 +49,51 @@ format_gre_tunnel (u8 * s, va_list * args) { gre_tunnel_t * t = va_arg (*args, gre_tunnel_t *); gre_main_t * gm = &gre_main; - - s = format (s, - "[%d] %U (src) %U (dst) payload %U outer_fib_index %d", - t - gm->tunnels, - format_ip4_address, &t->tunnel_src, - format_ip4_address, &t->tunnel_dst, - format_gre_tunnel_type, t->type, - t->outer_fib_index); + u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; + + if (!is_ipv6) + s = format (s, + "[%d] %U (src) %U (dst) payload %U outer_fib_index %d", + t - gm->tunnels, + format_ip4_address, &t->tunnel_src.ip4, + format_ip4_address, &t->tunnel_dst.fp_addr.ip4, + format_gre_tunnel_type, t->type, + t->outer_fib_index); + else + s = format (s, + "[%d] %U (src) %U (dst) payload %U outer_fib_index %d", + t - gm->tunnels, + format_ip6_address, &t->tunnel_src.ip6, + format_ip6_address, &t->tunnel_dst.fp_addr.ip6, + format_gre_tunnel_type, t->type, + t->outer_fib_index); return s; } static gre_tunnel_t * -gre_tunnel_db_find (const ip4_address_t *src, - const ip4_address_t *dst, - u32 out_fib_index) +gre_tunnel_db_find (const ip46_address_t *src, + const ip46_address_t *dst, + u32 out_fib_index, + u8 is_ipv6) { gre_main_t * gm = &gre_main; uword * p; - u64 key; - - key = gre_mk_key(src, dst, out_fib_index); + u64 key4, key6[4]; - p = hash_get (gm->tunnel_by_key, key); + if (!is_ipv6) + { + key4 = gre4_mk_key(&src->ip4, &dst->ip4, out_fib_index); + p = hash_get (gm->tunnel_by_key4, key4); + } + else + { + key6[0] = src->ip6.as_u64[0]; + key6[1] = src->ip6.as_u64[1]; + key6[2] = dst->ip6.as_u64[0]; + key6[3] = dst->ip6.as_u64[1]; + p = hash_get_mem (gm->tunnel_by_key6, key6); + } if (NULL == p) return (NULL); @@ -83,20 +105,49 @@ static void gre_tunnel_db_add (const gre_tunnel_t *t) { gre_main_t * gm = &gre_main; - u64 key; + u64 key4, key6[4], *key6_copy; + u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; - key = gre_mk_key(&t->tunnel_src, &t->tunnel_dst, t->outer_fib_index); - hash_set (gm->tunnel_by_key, key, t - gm->tunnels); + if (!is_ipv6) + { + key4 = gre4_mk_key(&t->tunnel_src.ip4, &t->tunnel_dst.fp_addr.ip4, + t->outer_fib_index); + hash_set (gm->tunnel_by_key4, key4, t - gm->tunnels); + } + else + { + key6[0] = t->tunnel_src.ip6.as_u64[0]; + key6[1] = t->tunnel_src.ip6.as_u64[1]; + key6[2] = t->tunnel_dst.fp_addr.ip6.as_u64[0]; + key6[3] = t->tunnel_dst.fp_addr.ip6.as_u64[1]; + key6_copy = clib_mem_alloc (sizeof (key6)); + clib_memcpy (key6_copy, key6, sizeof (key6)); + hash_set_mem (gm->tunnel_by_key6, key6_copy, t - gm->tunnels); + } } static void gre_tunnel_db_remove (const gre_tunnel_t *t) { gre_main_t * gm = &gre_main; - u64 key; + u64 key4, key6[4]; + u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; + + if (!is_ipv6) + { + key4 = gre4_mk_key(&t->tunnel_src.ip4, &t->tunnel_dst.fp_addr.ip4, + t->outer_fib_index); + hash_unset (gm->tunnel_by_key4, key4); + } + else + { + key6[0] = t->tunnel_src.ip6.as_u64[0]; + key6[1] = t->tunnel_src.ip6.as_u64[1]; + key6[2] = t->tunnel_dst.fp_addr.ip6.as_u64[0]; + key6[3] = t->tunnel_dst.fp_addr.ip6.as_u64[1]; + hash_unset_mem (gm->tunnel_by_key6, key6); + } - key = gre_mk_key(&t->tunnel_src, &t->tunnel_dst, t->outer_fib_index); - hash_unset (gm->tunnel_by_key, key); } static gre_tunnel_t * @@ -230,26 +281,31 @@ const static fib_node_vft_t gre_vft = { .fnv_back_walk = gre_tunnel_back_walk, }; -static int +static int vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, u32 * sw_if_indexp) { gre_main_t * gm = &gre_main; vnet_main_t * vnm = gm->vnet_main; - ip4_main_t * im = &ip4_main; + ip4_main_t * im4 = &ip4_main; + ip6_main_t * im6 = &ip6_main; gre_tunnel_t * t; vnet_hw_interface_t * hi; u32 hw_if_index, sw_if_index; u32 outer_fib_index; u8 address[6]; clib_error_t *error; + u8 is_ipv6 = a->is_ipv6; - outer_fib_index = ip4_fib_index_from_table_id(a->outer_fib_id); + if (!is_ipv6) + outer_fib_index = ip4_fib_index_from_table_id(a->outer_fib_id); + else + outer_fib_index = ip6_fib_index_from_table_id(a->outer_fib_id); if (~0 == outer_fib_index) return VNET_API_ERROR_NO_SUCH_FIB; - t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id); + t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id, a->is_ipv6); if (NULL != t) return VNET_API_ERROR_INVALID_VALUE; @@ -336,37 +392,40 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, vec_validate_init_empty (gm->tunnel_index_by_sw_if_index, sw_if_index, ~0); gm->tunnel_index_by_sw_if_index[sw_if_index] = t - gm->tunnels; - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); + if (!is_ipv6) + { + vec_validate (im4->fib_index_by_sw_if_index, sw_if_index); + hi->min_packet_bytes = 64 + sizeof (gre_header_t) + sizeof (ip4_header_t); + } + else + { + vec_validate (im6->fib_index_by_sw_if_index, sw_if_index); + hi->min_packet_bytes = 64 + sizeof (gre_header_t) + sizeof (ip6_header_t); + } - hi->min_packet_bytes = 64 + sizeof (gre_header_t) + sizeof (ip4_header_t); hi->per_packet_overhead_bytes = /* preamble */ 8 + /* inter frame gap */ 12; /* Standard default gre MTU. */ hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000; - clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); - clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); - - gre_tunnel_db_add(t); - /* * source the FIB entry for the tunnel's destination * and become a child thereof. The tunnel will then get poked * when the forwarding for the entry updates, and the tunnel can * re-stack accordingly */ - const fib_prefix_t tun_dst_pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = t->tunnel_dst, - } - }; + + clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); + t->tunnel_dst.fp_len = !is_ipv6 ? 32 : 128; + t->tunnel_dst.fp_proto = !is_ipv6 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + t->tunnel_dst.fp_addr = a->dst; + + gre_tunnel_db_add(t); t->fib_entry_index = fib_table_entry_special_add(outer_fib_index, - &tun_dst_pfx, + &t->tunnel_dst, FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE, ADJ_INDEX_INVALID); @@ -375,12 +434,9 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, FIB_NODE_TYPE_GRE_TUNNEL, t - gm->tunnels); - clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); - clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); - if (GRE_TUNNEL_TYPE_TEB == t->type) { - t->l2_adj_index = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + t->l2_adj_index = adj_nbr_add_or_lock(t->tunnel_dst.fp_proto, VNET_LINK_ETHERNET, &zero_addr, sw_if_index); @@ -393,7 +449,7 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, return 0; } -static int +static int vnet_gre_tunnel_delete (vnet_gre_add_del_tunnel_args_t *a, u32 * sw_if_indexp) { @@ -402,7 +458,7 @@ vnet_gre_tunnel_delete (vnet_gre_add_del_tunnel_args_t *a, gre_tunnel_t * t; u32 sw_if_index; - t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id); + t = gre_tunnel_db_find(&a->src, &a->dst, a->outer_fib_id, a->is_ipv6); if (NULL == t) return VNET_API_ERROR_NO_SUCH_ENTRY; @@ -484,7 +540,7 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, * line_input = &_line_input; vnet_gre_add_del_tunnel_args_t _a, * a = &_a; - ip4_address_t src, dst; + ip46_address_t src, dst; u32 outer_fib_id = 0; u8 teb = 0; int rv; @@ -492,6 +548,8 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, u8 is_add = 1; u32 sw_if_index; clib_error_t *error = NULL; + u8 ipv4_set = 0; + u8 ipv6_set = 0; /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -500,11 +558,19 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "del")) is_add = 0; - else if (unformat (line_input, "src %U", unformat_ip4_address, &src)) + else if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4)) { num_m_args++; - else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst)) + ipv4_set = 1; + } else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4)) { num_m_args++; - else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id)) + ipv4_set = 1; + } else if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6)) { + num_m_args++; + ipv6_set = 1; + } else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6)) { + num_m_args++; + ipv6_set = 1; + } else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id)) ; else if (unformat (line_input, "teb")) teb = 1; @@ -522,17 +588,37 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, goto done; } - if (memcmp (&src, &dst, sizeof(src)) == 0) + if ((ipv4_set && memcmp (&src.ip4, &dst.ip4, sizeof(src.ip4)) == 0) || + (ipv6_set && memcmp (&src.ip6, &dst.ip6, sizeof(src.ip6)) == 0)) { error = clib_error_return (0, "src and dst are identical"); goto done; } + if (ipv4_set && ipv6_set) + return clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + + if ((ipv4_set && memcmp (&dst.ip4, &zero_addr.ip4, sizeof(dst.ip4)) == 0) || + (ipv6_set && memcmp (&dst.ip6, &zero_addr.ip6, sizeof(dst.ip6)) == 0)) + { + error = clib_error_return (0, "dst address cannot be zero"); + goto done; + } + memset (a, 0, sizeof (*a)); a->outer_fib_id = outer_fib_id; a->teb = teb; - clib_memcpy(&a->src, &src, sizeof(src)); - clib_memcpy(&a->dst, &dst, sizeof(dst)); + a->is_ipv6 = ipv6_set; + if (!ipv6_set) + { + clib_memcpy(&a->src.ip4, &src.ip4, sizeof(src.ip4)); + clib_memcpy(&a->dst.ip4, &dst.ip4, sizeof(dst.ip4)); + } + else + { + clib_memcpy(&a->src.ip6, &src.ip6, sizeof(src.ip6)); + clib_memcpy(&a->dst.ip6, &dst.ip6, sizeof(dst.ip6)); + } if (is_add) rv = vnet_gre_tunnel_add(a, &sw_if_index); diff --git a/src/vnet/gre/node.c b/src/vnet/gre/node.c index 5926e83d..2683586e 100644 --- a/src/vnet/gre/node.c +++ b/src/vnet/gre/node.c @@ -39,8 +39,9 @@ typedef enum { typedef struct { u32 tunnel_id; u32 length; - ip4_address_t src; - ip4_address_t dst; + ip46_address_t src; + ip46_address_t dst; + u8 is_ipv6; } gre_rx_trace_t; u8 * format_gre_rx_trace (u8 * s, va_list * args) @@ -48,28 +49,41 @@ u8 * format_gre_rx_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); gre_rx_trace_t * t = va_arg (*args, gre_rx_trace_t *); - + s = format (s, "GRE: tunnel %d len %d src %U dst %U", t->tunnel_id, clib_net_to_host_u16(t->length), - format_ip4_address, &t->src.as_u8, - format_ip4_address, &t->dst.as_u8); + format_ip46_address, &t->src, IP46_TYPE_ANY, + format_ip46_address, &t->dst, IP46_TYPE_ANY); return s; } -static uword +typedef struct { + /* Sparse vector mapping gre protocol in network byte order + to next index. */ + u16 * next_by_protocol; +} gre_input_runtime_t; + +always_inline uword gre_input (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) + vlib_frame_t * from_frame, + u8 is_ipv6) { gre_main_t * gm = &gre_main; __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next; - u64 cached_tunnel_key = (u64) ~0; + u64 cached_tunnel_key4; + u64 cached_tunnel_key6[4]; u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0; u32 cpu_index = os_get_cpu_number(); u32 len; vnet_interface_main_t *im = &gm->vnet_main->interface_main; + if (!is_ipv6) + memset (&cached_tunnel_key4, 0xff, sizeof(cached_tunnel_key4)); + else + memset (&cached_tunnel_key6, 0xff, sizeof(cached_tunnel_key6)); + from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -90,7 +104,12 @@ gre_input (vlib_main_t * vm, u16 version0, version1; int verr0, verr1; u32 i0, i1, next0, next1, protocol0, protocol1; - ip4_header_t *ip0, *ip1; + ip4_header_t *ip4_0, *ip4_1; + ip6_header_t *ip6_0, *ip6_1; + u32 ip4_tun_src0, ip4_tun_dst0; + u32 ip4_tun_src1, ip4_tun_dst1; + u64 ip6_tun_src0[2], ip6_tun_dst0[2]; + u64 ip6_tun_src1[2], ip6_tun_dst1[2]; /* Prefetch next iteration. */ { @@ -118,18 +137,38 @@ gre_input (vlib_main_t * vm, b0 = vlib_get_buffer (vm, bi0); b1 = vlib_get_buffer (vm, bi1); - /* ip4_local hands us the ip header, not the gre header */ - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); - - /* Save src + dst ip4 address, e.g. for mpls-o-gre */ - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; - vnet_buffer(b1)->gre.src = ip1->src_address.as_u32; - vnet_buffer(b1)->gre.dst = ip1->dst_address.as_u32; - - vlib_buffer_advance (b0, sizeof (*ip0)); - vlib_buffer_advance (b1, sizeof (*ip1)); + if (!is_ipv6) + { + /* ip4_local hands us the ip header, not the gre header */ + ip4_0 = vlib_buffer_get_current (b0); + ip4_1 = vlib_buffer_get_current (b1); + /* Save src + dst ip4 address, e.g. for mpls-o-gre */ + ip4_tun_src0 = ip4_0->src_address.as_u32; + ip4_tun_dst0 = ip4_0->dst_address.as_u32; + ip4_tun_src1 = ip4_1->src_address.as_u32; + ip4_tun_dst1 = ip4_1->dst_address.as_u32; + + vlib_buffer_advance (b0, sizeof (*ip4_0)); + vlib_buffer_advance (b1, sizeof (*ip4_1)); + } + else + { + /* ip6_local hands us the ip header, not the gre header */ + ip6_0 = vlib_buffer_get_current (b0); + ip6_1 = vlib_buffer_get_current (b1); + /* Save src + dst ip6 address, e.g. for mpls-o-gre */ + ip6_tun_src0[0] = ip6_0->src_address.as_u64[0]; + ip6_tun_src0[1] = ip6_0->src_address.as_u64[1]; + ip6_tun_dst0[0] = ip6_0->dst_address.as_u64[0]; + ip6_tun_dst0[1] = ip6_0->dst_address.as_u64[1]; + ip6_tun_src1[0] = ip6_1->src_address.as_u64[0]; + ip6_tun_src1[1] = ip6_1->src_address.as_u64[1]; + ip6_tun_dst1[0] = ip6_1->dst_address.as_u64[0]; + ip6_tun_dst1[1] = ip6_1->dst_address.as_u64[1]; + + vlib_buffer_advance (b0, sizeof (*ip6_0)); + vlib_buffer_advance (b1, sizeof (*ip6_1)); + } h0 = vlib_buffer_get_current (b0); h1 = vlib_buffer_get_current (b1); @@ -164,16 +203,34 @@ gre_input (vlib_main_t * vm, || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT || next0 == GRE_INPUT_NEXT_MPLS_INPUT)) { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - if (cached_tunnel_key != key) + u64 key4, key6[4]; + if (!is_ipv6) + { + key4 = ((u64)(ip4_tun_dst0) << 32) | (u64)(ip4_tun_src0); + } + else + { + key6[0] = ip6_tun_dst0[0]; + key6[1] = ip6_tun_dst0[1]; + key6[2] = ip6_tun_src0[0]; + key6[3] = ip6_tun_src0[1]; + } + + if ((!is_ipv6 && cached_tunnel_key4 != key4) || + (is_ipv6 && cached_tunnel_key6[0] != key6[0] && + cached_tunnel_key6[1] != key6[1] && + cached_tunnel_key6[2] != key6[2] && + cached_tunnel_key6[3] != key6[3])) { vnet_hw_interface_t * hi; gre_tunnel_t * t; uword * p; - p = hash_get (gm->tunnel_by_key, key); + if (!is_ipv6) + p = hash_get (gm->tunnel_by_key4, key4); + else + p = hash_get_mem (gm->tunnel_by_key6, key6); if (!p) { next0 = GRE_INPUT_NEXT_DROP; @@ -213,16 +270,34 @@ drop0: || next1 == GRE_INPUT_NEXT_ETHERNET_INPUT || next1 == GRE_INPUT_NEXT_MPLS_INPUT)) { - u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) | - (u64)(vnet_buffer(b1)->gre.src); - - if (cached_tunnel_key != key) + u64 key4, key6[4]; + if (!is_ipv6) + { + key4 = ((u64)(ip4_tun_dst1) << 32) | (u64)(ip4_tun_src1); + } + else + { + key6[0] = ip6_tun_dst1[0]; + key6[1] = ip6_tun_dst1[1]; + key6[2] = ip6_tun_src1[0]; + key6[3] = ip6_tun_src1[1]; + } + + if ((!is_ipv6 && cached_tunnel_key4 != key4) || + (is_ipv6 && cached_tunnel_key6[0] != key6[0] && + cached_tunnel_key6[1] != key6[1] && + cached_tunnel_key6[2] != key6[2] && + cached_tunnel_key6[3] != key6[3])) { vnet_hw_interface_t * hi; gre_tunnel_t * t; uword * p; - p = hash_get (gm->tunnel_by_key, key); + if (!is_ipv6) + p = hash_get (gm->tunnel_by_key4, key4); + else + p = hash_get_mem (gm->tunnel_by_key6, key6); + if (!p) { next1 = GRE_INPUT_NEXT_DROP; @@ -262,9 +337,20 @@ drop1: gre_rx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_id = tunnel_sw_if_index; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; + if (!is_ipv6) + { + tr->length = ip4_0->length; + tr->src.ip4.as_u32 = ip4_0->src_address.as_u32; + tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32; + } + else + { + tr->length = ip6_0->payload_length; + tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0]; + tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1]; + tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0]; + tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1]; + } } if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) @@ -272,9 +358,20 @@ drop1: gre_rx_trace_t *tr = vlib_add_trace (vm, node, b1, sizeof (*tr)); tr->tunnel_id = tunnel_sw_if_index; - tr->length = ip1->length; - tr->src.as_u32 = ip1->src_address.as_u32; - tr->dst.as_u32 = ip1->dst_address.as_u32; + if (!is_ipv6) + { + tr->length = ip4_1->length; + tr->src.ip4.as_u32 = ip4_1->src_address.as_u32; + tr->dst.ip4.as_u32 = ip4_1->dst_address.as_u32; + } + else + { + tr->length = ip6_1->payload_length; + tr->src.ip6.as_u64[0] = ip6_1->src_address.as_u64[0]; + tr->src.ip6.as_u64[1] = ip6_1->src_address.as_u64[1]; + tr->dst.ip6.as_u64[0] = ip6_1->dst_address.as_u64[0]; + tr->dst.ip6.as_u64[1] = ip6_1->dst_address.as_u64[1]; + } } vlib_buffer_advance (b0, sizeof (*h0)); @@ -284,16 +381,19 @@ drop1: to_next, n_left_to_next, bi0, bi1, next0, next1); } - + while (n_left_from > 0 && n_left_to_next > 0) { u32 bi0; vlib_buffer_t * b0; gre_header_t * h0; - ip4_header_t * ip0; + ip4_header_t * ip4_0; + ip6_header_t * ip6_0; u16 version0; int verr0; u32 i0, next0; + u32 ip4_tun_src0, ip4_tun_dst0; + u32 ip6_tun_src0[4], ip6_tun_dst0[4]; bi0 = from[0]; to_next[0] = bi0; @@ -303,22 +403,35 @@ drop1: n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); - ip0 = vlib_buffer_get_current (b0); + ip4_0 = vlib_buffer_get_current (b0); + ip6_0 = (void *)ip4_0; + + if (!is_ipv6) + { + ip4_tun_src0 = ip4_0->src_address.as_u32; + ip4_tun_dst0 = ip4_0->dst_address.as_u32; - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; + vlib_buffer_advance (b0, sizeof (*ip4_0)); + } + else + { + ip6_tun_src0[0] = ip6_0->src_address.as_u64[0]; + ip6_tun_src0[1] = ip6_0->src_address.as_u64[1]; + ip6_tun_dst0[0] = ip6_0->dst_address.as_u64[0]; + ip6_tun_dst0[1] = ip6_0->dst_address.as_u64[1]; - vlib_buffer_advance (b0, sizeof (*ip0)); + vlib_buffer_advance (b0, sizeof (*ip6_0)); + } h0 = vlib_buffer_get_current (b0); i0 = sparse_vec_index (gm->next_by_protocol, h0->protocol); next0 = vec_elt(gm->next_by_protocol, i0); - b0->error = + b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE]; - + version0 = clib_net_to_host_u16 (h0->flags_and_version); verr0 = version0 & GRE_VERSION_MASK; b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] @@ -335,16 +448,34 @@ drop1: || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT || next0 == GRE_INPUT_NEXT_MPLS_INPUT)) { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - - if (cached_tunnel_key != key) + u64 key4, key6[4]; + if (!is_ipv6) + { + key4 = ((u64)(ip4_tun_dst0) << 32) | (u64)(ip4_tun_src0); + } + else { + key6[0] = ip6_tun_dst0[0]; + key6[1] = ip6_tun_dst0[1]; + key6[2] = ip6_tun_src0[0]; + key6[3] = ip6_tun_src0[1]; + } + + if ((!is_ipv6 && cached_tunnel_key4 != key4) || + (is_ipv6 && cached_tunnel_key6[0] != key6[0] && + cached_tunnel_key6[1] != key6[1] && + cached_tunnel_key6[2] != key6[2] && + cached_tunnel_key6[3] != key6[3])) + { vnet_hw_interface_t * hi; gre_tunnel_t * t; uword * p; - p = hash_get (gm->tunnel_by_key, key); + if (!is_ipv6) + p = hash_get (gm->tunnel_by_key4, key4); + else + p = hash_get_mem (gm->tunnel_by_key6, key6); + if (!p) { next0 = GRE_INPUT_NEXT_DROP; @@ -379,14 +510,25 @@ drop1: vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; drop: - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { - gre_rx_trace_t *tr = vlib_add_trace (vm, node, + gre_rx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_id = tunnel_sw_if_index; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; + if (!is_ipv6) + { + tr->length = ip4_0->length; + tr->src.ip4.as_u32 = ip4_0->src_address.as_u32; + tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32; + } + else + { + tr->length = ip6_0->payload_length; + tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0]; + tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1]; + tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0]; + tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1]; + } } vlib_buffer_advance (b0, sizeof (*h0)); @@ -398,20 +540,36 @@ drop: vlib_put_next_frame (vm, node, next_index, n_left_to_next); } - vlib_node_increment_counter (vm, gre_input_node.index, + vlib_node_increment_counter (vm, !is_ipv6 ? gre4_input_node.index : gre6_input_node.index, GRE_ERROR_PKTS_DECAP, from_frame->n_vectors); return from_frame->n_vectors; } +static uword +gre4_input (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return gre_input(vm, node, from_frame, /* is_ip6 */ 0); +} + +static uword +gre6_input (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return gre_input(vm, node, from_frame, /* is_ip6 */ 1); +} + static char * gre_error_strings[] = { #define gre_error(n,s) s, #include "error.def" #undef gre_error }; -VLIB_REGISTER_NODE (gre_input_node) = { - .function = gre_input, - .name = "gre-input", +VLIB_REGISTER_NODE (gre4_input_node) = { + .function = gre4_input, + .name = "gre4-input", /* Takes a vector of packets. */ .vector_size = sizeof (u32), @@ -430,7 +588,31 @@ VLIB_REGISTER_NODE (gre_input_node) = { .unformat_buffer = unformat_gre_header, }; -VLIB_NODE_FUNCTION_MULTIARCH (gre_input_node, gre_input) +VLIB_REGISTER_NODE (gre6_input_node) = { + .function = gre6_input, + .name = "gre6-input", + /* Takes a vector of packets. */ + .vector_size = sizeof (u32), + + .runtime_data_bytes = sizeof (gre_input_runtime_t), + + .n_errors = GRE_N_ERROR, + .error_strings = gre_error_strings, + + .n_next_nodes = GRE_INPUT_N_NEXT, + .next_nodes = { +#define _(s,n) [GRE_INPUT_NEXT_##s] = n, + foreach_gre_input_next +#undef _ + }, + + .format_buffer = format_gre_header_with_length, + .format_trace = format_gre_rx_trace, + .unformat_buffer = unformat_gre_header, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (gre4_input_node, gre4_input) +VLIB_NODE_FUNCTION_MULTIARCH (gre6_input_node, gre6_input) void gre_register_input_protocol (vlib_main_t * vm, @@ -440,6 +622,7 @@ gre_register_input_protocol (vlib_main_t * vm, gre_main_t * em = &gre_main; gre_protocol_info_t * pi; u16 * n; + u32 i; { clib_error_t * error = vlib_call_init_function (vm, gre_input_init); @@ -449,9 +632,9 @@ gre_register_input_protocol (vlib_main_t * vm, pi = gre_get_protocol_info (em, protocol); pi->node_index = node_index; - pi->next_index = vlib_node_add_next (vm, - gre_input_node.index, - node_index); + pi->next_index = vlib_node_add_next (vm, gre4_input_node.index, node_index); + i = vlib_node_add_next (vm, gre6_input_node.index, node_index); + ASSERT(i == pi->next_index); /* Setup gre protocol -> next index sparse vector mapping. */ n = sparse_vec_validate (em->next_by_protocol, @@ -476,13 +659,14 @@ static clib_error_t * gre_input_init (vlib_main_t * vm) vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input; { - clib_error_t * error; + clib_error_t * error; error = vlib_call_init_function (vm, gre_init); if (error) clib_error_report (error); } - gre_setup_node (vm, gre_input_node.index); + gre_setup_node (vm, gre4_input_node.index); + gre_setup_node (vm, gre6_input_node.index); gm->next_by_protocol = sparse_vec_new (/* elt bytes */ sizeof (gm->next_by_protocol[0]), @@ -501,19 +685,19 @@ static clib_error_t * gre_input_init (vlib_main_t * vm) gre_register_input_protocol (vm, GRE_PROTOCOL_teb, ethernet_input->index); - gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, + gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, ip4_input->index); - gre_register_input_protocol (vm, GRE_PROTOCOL_ip6, + gre_register_input_protocol (vm, GRE_PROTOCOL_ip6, ip6_input->index); gre_register_input_protocol (vm, GRE_PROTOCOL_mpls_unicast, mpls_unicast_input->index); - ip4_register_protocol (IP_PROTOCOL_GRE, gre_input_node.index); + ip4_register_protocol (IP_PROTOCOL_GRE, gre4_input_node.index); + ip6_register_protocol (IP_PROTOCOL_GRE, gre6_input_node.index); return 0; } VLIB_INIT_FUNCTION (gre_input_init); - diff --git a/src/vnet/ipsec-gre/node.c b/src/vnet/ipsec-gre/node.c index d20f248a..217d323a 100644 --- a/src/vnet/ipsec-gre/node.c +++ b/src/vnet/ipsec-gre/node.c @@ -92,6 +92,8 @@ ipsec_gre_input (vlib_main_t * vm, u32 n_left_from, next_index, * from, * to_next; u64 cached_tunnel_key = (u64) ~0; u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index; + u32 tun_src0, tun_dst0; + u32 tun_src1, tun_dst1; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -146,10 +148,10 @@ ipsec_gre_input (vlib_main_t * vm, ip1 = vlib_buffer_get_current (b1); /* Save src + dst ip4 address */ - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; - vnet_buffer(b1)->gre.src = ip1->src_address.as_u32; - vnet_buffer(b1)->gre.dst = ip1->dst_address.as_u32; + tun_src0 = ip0->src_address.as_u32; + tun_dst0 = ip0->dst_address.as_u32; + tun_src1 = ip1->src_address.as_u32; + tun_dst1 = ip1->dst_address.as_u32; vlib_buffer_advance (b0, sizeof (*ip0)); vlib_buffer_advance (b1, sizeof (*ip1)); @@ -197,8 +199,7 @@ ipsec_gre_input (vlib_main_t * vm, /* For L2 payload set input sw_if_index to GRE tunnel for learning */ if (PREDICT_TRUE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); + u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0); if (cached_tunnel_key != key) { @@ -230,8 +231,7 @@ drop0: /* For L2 payload set input sw_if_index to GRE tunnel for learning */ if (PREDICT_TRUE(next1 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) { - u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) | - (u64)(vnet_buffer(b1)->gre.src); + u64 key = ((u64)(tun_dst1) << 32) | (u64)(tun_src1); if (cached_tunnel_key != key) { @@ -297,6 +297,7 @@ drop1: u16 version0, protocol0; int verr0; u32 next0; + u32 tun_src0, tun_dst0; bi0 = from[0]; to_next[0] = bi0; @@ -308,8 +309,8 @@ drop1: b0 = vlib_get_buffer (vm, bi0); ip0 = vlib_buffer_get_current (b0); - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; + tun_src0 = ip0->src_address.as_u32; + tun_dst0 = ip0->dst_address.as_u32; vlib_buffer_advance (b0, sizeof (*ip0)); @@ -337,8 +338,7 @@ drop1: /* For L2 payload set input sw_if_index to GRE tunnel for learning */ if (PREDICT_FALSE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); + u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0); if (cached_tunnel_key != key) { diff --git a/test/test_gre.py b/test/test_gre.py index f2a5e0b0..18b67dbd 100644 --- a/test/test_gre.py +++ b/test/test_gre.py @@ -5,7 +5,7 @@ from logging import * from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppDot1QSubint -from vpp_gre_interface import VppGreInterface +from vpp_gre_interface import VppGreInterface, VppGre6Interface from vpp_ip_route import VppIpRoute, VppRoutePath from vpp_papi_provider import L2_VTR_OP @@ -28,14 +28,19 @@ class TestGRE(VppTestCase): def setUp(self): super(TestGRE, self).setUp() - # create 2 pg interfaces - set one in a non-default table. - self.create_pg_interfaces(range(2)) - + # create 3 pg interfaces - set one in a non-default table. + self.create_pg_interfaces(range(3)) self.pg1.set_table_ip4(1) + for i in self.pg_interfaces: i.admin_up() - i.config_ip4() - i.resolve_arp() + + self.pg0.config_ip4() + self.pg0.resolve_arp() + self.pg1.config_ip4() + self.pg1.resolve_arp() + self.pg2.config_ip6() + self.pg2.resolve_ndp() def tearDown(self): super(TestGRE, self).tearDown() @@ -57,6 +62,19 @@ class TestGRE(VppTestCase): pkts.append(p) return pkts + def create_stream_ip6(self, src_if, src_ip, dst_ip): + pkts = [] + for i in range(0, 257): + info = self.create_packet_info(src_if, src_if) + payload = self.info_to_payload(info) + p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IPv6(src=src_ip, dst=dst_ip) / + UDP(sport=1234, dport=1234) / + Raw(payload)) + info.data = p.copy() + pkts.append(p) + return pkts + def create_tunnel_stream_4o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip): @@ -91,6 +109,23 @@ class TestGRE(VppTestCase): pkts.append(p) return pkts + def create_tunnel_stream_6o6(self, src_if, + tunnel_src, tunnel_dst, + src_ip, dst_ip): + pkts = [] + for i in range(0, 257): + info = self.create_packet_info(src_if, src_if) + payload = self.info_to_payload(info) + p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IPv6(src=tunnel_src, dst=tunnel_dst) / + GRE() / + IPv6(src=src_ip, dst=dst_ip) / + UDP(sport=1234, dport=1234) / + Raw(payload)) + info.data = p.copy() + pkts.append(p) + return pkts + def create_tunnel_stream_l2o4(self, src_if, tunnel_src, tunnel_dst): pkts = [] @@ -157,6 +192,33 @@ class TestGRE(VppTestCase): self.logger.error(ppp("Tx:", tx)) raise + def verify_tunneled_6o6(self, src_if, capture, sent, + tunnel_src, tunnel_dst): + + self.assertEqual(len(capture), len(sent)) + + for i in range(len(capture)): + try: + tx = sent[i] + rx = capture[i] + + tx_ip = tx[IPv6] + rx_ip = rx[IPv6] + + self.assertEqual(rx_ip.src, tunnel_src) + self.assertEqual(rx_ip.dst, tunnel_dst) + + rx_gre = GRE(str(rx_ip[IPv6].payload)) + rx_ip = rx_gre[IPv6] + + self.assertEqual(rx_ip.src, tx_ip.src) + self.assertEqual(rx_ip.dst, tx_ip.dst) + + except: + self.logger.error(ppp("Rx:", rx)) + self.logger.error(ppp("Tx:", tx)) + raise + def verify_tunneled_l2o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) @@ -275,7 +337,7 @@ class TestGRE(VppTestCase): raise def test_gre(self): - """ GRE tunnel Tests """ + """ GRE IPv4 tunnel Tests """ # # Create an L3 GRE tunnel. @@ -438,6 +500,79 @@ class TestGRE(VppTestCase): self.pg0.unconfig_ip6() + def test_gre6(self): + """ GRE IPv6 tunnel Tests """ + + # + # Create an L3 GRE tunnel. + # - set it admin up + # - assign an IP Address + # - Add a route via the tunnel + # + gre_if = VppGre6Interface(self, + self.pg2.local_ip6, + "1002::1") + gre_if.add_vpp_config() + gre_if.admin_up() + gre_if.config_ip6() + + route_via_tun = VppIpRoute(self, "4004::1", 128, + [VppRoutePath("0::0", + gre_if.sw_if_index, + is_ip6=1)], + is_ip6=1) + + route_via_tun.add_vpp_config() + + # + # Send a packet stream that is routed into the tunnel + # - they are all dropped since the tunnel's desintation IP + # is unresolved - or resolves via the default route - which + # which is a drop. + # + tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") + self.pg2.add_stream(tx) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + self.pg2.assert_nothing_captured( + remark="GRE packets forwarded without DIP resolved") + + # + # Add a route that resolves the tunnel's destination + # + route_tun_dst = VppIpRoute(self, "1002::1", 128, + [VppRoutePath(self.pg2.remote_ip6, + self.pg2.sw_if_index, + is_ip6=1)], + is_ip6=1) + route_tun_dst.add_vpp_config() + + # + # Send a packet stream that is routed into the tunnel + # - packets are GRE encapped + # + self.vapi.cli("clear trace") + tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") + self.pg2.add_stream(tx) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(len(tx)) + self.verify_tunneled_6o6(self.pg2, rx, tx, + self.pg2.local_ip6, "1002::1") + + # + # test case cleanup + # + route_tun_dst.remove_vpp_config() + route_via_tun.remove_vpp_config() + gre_if.remove_vpp_config() + + self.pg2.unconfig_ip6() + def test_gre_vrf(self): """ GRE tunnel VRF Tests """ diff --git a/test/vpp_gre_interface.py b/test/vpp_gre_interface.py index 58a68290..1c71875f 100644 --- a/test/vpp_gre_interface.py +++ b/test/vpp_gre_interface.py @@ -34,3 +34,38 @@ class VppGreInterface(VppInterface): r = self.test.vapi.gre_tunnel_add_del(s, d, outer_fib_id=self.t_outer_fib, is_add=0) + + +class VppGre6Interface(VppInterface): + """ + VPP GRE IPv6 interface + """ + + def __init__(self, test, src_ip, dst_ip, outer_fib_id=0, is_teb=0): + """ Create VPP loopback interface """ + self._sw_if_index = 0 + super(VppGre6Interface, self).__init__(test) + self._test = test + self.t_src = src_ip + self.t_dst = dst_ip + self.t_outer_fib = outer_fib_id + self.t_is_teb = is_teb + + def add_vpp_config(self): + s = socket.inet_pton(socket.AF_INET6, self.t_src) + d = socket.inet_pton(socket.AF_INET6, self.t_dst) + r = self.test.vapi.gre_tunnel_add_del(s, d, + outer_fib_id=self.t_outer_fib, + is_teb=self.t_is_teb, + is_ip6=1) + self._sw_if_index = r.sw_if_index + self.generate_remote_hosts() + + def remove_vpp_config(self): + s = socket.inet_pton(socket.AF_INET6, self.t_src) + d = socket.inet_pton(socket.AF_INET6, self.t_dst) + self.unconfig() + r = self.test.vapi.gre_tunnel_add_del(s, d, + outer_fib_id=self.t_outer_fib, + is_add=0, + is_ip6=1) -- cgit 1.2.3-korg From 586afd762bfa149f5ca167bd5fd5a0cd59ce94fe Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Wed, 5 Apr 2017 19:18:20 +0200 Subject: Use thread local storage for thread index This patch deprecates stack-based thread identification, Also removes requirement that thread stacks are adjacent. Finally, possibly annoying for some folks, it renames all occurences of cpu_index and cpu_number with thread index. Using word "cpu" is misleading here as thread can be migrated ti different CPU, and also it is not related to linux cpu index. Change-Id: I68cdaf661e701d2336fc953dcb9978d10a70f7c1 Signed-off-by: Damjan Marion --- src/examples/srv6-sample-localsid/node.c | 4 +- src/plugins/dpdk/buffer.c | 2 +- src/plugins/dpdk/device/device.c | 8 +- src/plugins/dpdk/device/dpdk_priv.h | 8 +- src/plugins/dpdk/device/init.c | 2 +- src/plugins/dpdk/device/node.c | 32 +++--- src/plugins/dpdk/hqos/hqos.c | 16 +-- src/plugins/dpdk/ipsec/cli.c | 8 +- src/plugins/dpdk/ipsec/crypto_node.c | 4 +- src/plugins/dpdk/ipsec/esp.h | 4 +- src/plugins/dpdk/ipsec/esp_decrypt.c | 4 +- src/plugins/dpdk/ipsec/esp_encrypt.c | 5 +- src/plugins/dpdk/ipsec/ipsec.c | 2 +- src/plugins/dpdk/ipsec/ipsec.h | 4 +- src/plugins/dpdk/main.c | 2 +- src/plugins/flowperpkt/l2_node.c | 2 +- src/plugins/flowperpkt/node.c | 2 +- src/plugins/ioam/export-common/ioam_export.h | 6 +- .../ioam/ip6/ioam_cache_tunnel_select_node.c | 16 +-- src/plugins/ixge/ixge.c | 2 +- src/plugins/lb/lb.c | 8 +- src/plugins/lb/node.c | 22 ++-- src/plugins/lb/refcount.c | 8 +- src/plugins/lb/refcount.h | 4 +- src/plugins/memif/node.c | 35 +++--- src/plugins/snat/in2out.c | 110 +++++++++--------- src/plugins/snat/out2in.c | 102 ++++++++--------- src/plugins/snat/snat.h | 10 +- src/vlib/buffer.c | 6 +- src/vlib/buffer_funcs.h | 4 +- src/vlib/cli.c | 6 +- src/vlib/counter.h | 16 +-- src/vlib/error.c | 2 +- src/vlib/global_funcs.h | 2 +- src/vlib/main.c | 14 +-- src/vlib/main.h | 2 +- src/vlib/node.c | 2 +- src/vlib/node.h | 6 +- src/vlib/node_funcs.h | 8 +- src/vlib/threads.c | 69 ++++------- src/vlib/threads.h | 21 ++-- src/vlib/unix/cj.c | 7 +- src/vlib/unix/cj.h | 2 +- src/vlib/unix/main.c | 43 +++---- src/vnet/adj/adj_l2.c | 4 +- src/vnet/adj/adj_midchain.c | 8 +- src/vnet/adj/adj_nsh.c | 4 +- src/vnet/classify/vnet_classify.c | 16 +-- src/vnet/cop/ip4_whitelist.c | 8 +- src/vnet/cop/ip6_whitelist.c | 8 +- src/vnet/devices/af_packet/node.c | 20 ++-- src/vnet/devices/devices.c | 61 +++++----- src/vnet/devices/devices.h | 18 +-- src/vnet/devices/netmap/node.c | 24 ++-- src/vnet/devices/ssvm/node.c | 6 +- src/vnet/devices/virtio/vhost-user.c | 127 +++++++++++---------- src/vnet/dpo/lookup_dpo.c | 20 ++-- src/vnet/dpo/replicate_dpo.c | 12 +- src/vnet/ethernet/arp.c | 2 +- src/vnet/ethernet/interface.c | 7 +- src/vnet/ethernet/node.c | 14 +-- src/vnet/gre/node.c | 8 +- src/vnet/interface.h | 2 +- src/vnet/interface_output.c | 53 ++++----- src/vnet/ip/ip4_forward.c | 34 +++--- src/vnet/ip/ip4_input.c | 8 +- src/vnet/ip/ip6_forward.c | 24 ++-- src/vnet/ip/ip6_input.c | 8 +- src/vnet/ip/ip6_neighbor.c | 4 +- src/vnet/ipsec/esp.h | 8 +- src/vnet/ipsec/esp_decrypt.c | 13 ++- src/vnet/ipsec/esp_encrypt.c | 13 ++- src/vnet/ipsec/ikev2.c | 64 ++++++----- src/vnet/ipsec/ipsec.h | 12 +- src/vnet/ipsec/ipsec_if.c | 2 +- src/vnet/l2/l2_bvi.h | 2 +- src/vnet/l2/l2_input.c | 14 +-- src/vnet/l2/l2_output.c | 6 +- src/vnet/l2tp/decap.c | 2 +- src/vnet/l2tp/encap.c | 2 +- src/vnet/l2tp/l2tp.c | 6 +- src/vnet/lisp-gpe/decap.c | 16 +-- src/vnet/lldp/lldp_input.c | 2 +- src/vnet/map/ip4_map.c | 14 +-- src/vnet/map/ip4_map_t.c | 12 +- src/vnet/map/ip6_map.c | 19 +-- src/vnet/map/ip6_map_t.c | 12 +- src/vnet/mpls/mpls_input.c | 8 +- src/vnet/mpls/mpls_lookup.c | 20 ++-- src/vnet/mpls/mpls_output.c | 10 +- src/vnet/pg/input.c | 4 +- src/vnet/replication.c | 20 ++-- src/vnet/replication.h | 2 +- src/vnet/session/node.c | 2 +- src/vnet/sr/sr_localsid.c | 44 +++---- src/vnet/tcp/builtin_client.c | 2 +- src/vnet/tcp/tcp.c | 8 +- src/vnet/tcp/tcp_debug.h | 2 +- src/vnet/tcp/tcp_input.c | 10 +- src/vnet/tcp/tcp_output.c | 20 ++-- src/vnet/udp/udp_input.c | 2 +- src/vnet/unix/tapcli.c | 2 +- src/vnet/unix/tuntap.c | 4 +- src/vnet/vxlan-gpe/decap.c | 10 +- src/vnet/vxlan-gpe/encap.c | 12 +- src/vnet/vxlan/decap.c | 10 +- src/vnet/vxlan/encap.c | 12 +- src/vpp/stats/stats.c | 14 +-- src/vpp/stats/stats.h | 2 +- 109 files changed, 790 insertions(+), 791 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/examples/srv6-sample-localsid/node.c b/src/examples/srv6-sample-localsid/node.c index 7bae9cd7..e83e2352 100644 --- a/src/examples/srv6-sample-localsid/node.c +++ b/src/examples/srv6-sample-localsid/node.c @@ -114,7 +114,7 @@ srv6_localsid_sample_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_fram from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -168,7 +168,7 @@ srv6_localsid_sample_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_fram /* This increments the SRv6 per LocalSID counters.*/ vlib_increment_combined_counter (((next0 == SRV6_SAMPLE_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : &(sm->sr_ls_valid_counters)), - cpu_index, + thread_index, ls0 - sm->localsids, 1, vlib_buffer_length_in_chain (vm, b0)); diff --git a/src/plugins/dpdk/buffer.c b/src/plugins/dpdk/buffer.c index 2765c292..c80b3fa8 100644 --- a/src/plugins/dpdk/buffer.c +++ b/src/plugins/dpdk/buffer.c @@ -132,7 +132,7 @@ dpdk_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index) u32 merge_index; int i; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); f = vlib_buffer_get_free_list (vm, free_list_index); diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c index 50b26689..91661246 100644 --- a/src/plugins/dpdk/device/device.c +++ b/src/plugins/dpdk/device/device.c @@ -243,7 +243,7 @@ static_always_inline ASSERT (ring->tx_tail == 0); n_retry = 16; - queue_id = vm->cpu_index; + queue_id = vm->thread_index; do { @@ -266,7 +266,7 @@ static_always_inline { /* no wrap, transmit in one burst */ dpdk_device_hqos_per_worker_thread_t *hqos = - &xd->hqos_wt[vm->cpu_index]; + &xd->hqos_wt[vm->thread_index]; ASSERT (hqos->swq != NULL); @@ -332,7 +332,7 @@ dpdk_buffer_recycle (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t * b, u32 bi, struct rte_mbuf **mbp) { dpdk_main_t *dm = &dpdk_main; - u32 my_cpu = vm->cpu_index; + u32 my_cpu = vm->thread_index; struct rte_mbuf *mb_new; if (PREDICT_FALSE (b->flags & VLIB_BUFFER_RECYCLE) == 0) @@ -376,7 +376,7 @@ dpdk_interface_tx (vlib_main_t * vm, tx_ring_hdr_t *ring; u32 n_on_ring; - my_cpu = vm->cpu_index; + my_cpu = vm->thread_index; queue_id = my_cpu; diff --git a/src/plugins/dpdk/device/dpdk_priv.h b/src/plugins/dpdk/device/dpdk_priv.h index dd40ff48..52b4ca4b 100644 --- a/src/plugins/dpdk/device/dpdk_priv.h +++ b/src/plugins/dpdk/device/dpdk_priv.h @@ -79,7 +79,7 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now) { vlib_simple_counter_main_t *cm; vnet_main_t *vnm = vnet_get_main (); - u32 my_cpu = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u64 rxerrors, last_rxerrors; /* only update counters for PMD interfaces */ @@ -96,7 +96,7 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now) cm = vec_elt_at_index (vnm->interface_main.sw_if_counters, VNET_INTERFACE_COUNTER_RX_NO_BUF); - vlib_increment_simple_counter (cm, my_cpu, xd->vlib_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, xd->vlib_sw_if_index, xd->stats.rx_nombuf - xd->last_stats.rx_nombuf); } @@ -107,7 +107,7 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now) cm = vec_elt_at_index (vnm->interface_main.sw_if_counters, VNET_INTERFACE_COUNTER_RX_MISS); - vlib_increment_simple_counter (cm, my_cpu, xd->vlib_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, xd->vlib_sw_if_index, xd->stats.imissed - xd->last_stats.imissed); } @@ -119,7 +119,7 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now) cm = vec_elt_at_index (vnm->interface_main.sw_if_counters, VNET_INTERFACE_COUNTER_RX_ERROR); - vlib_increment_simple_counter (cm, my_cpu, xd->vlib_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, xd->vlib_sw_if_index, rxerrors - last_rxerrors); } diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index 538db6cb..7eaf8da7 100755 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -324,7 +324,7 @@ dpdk_port_setup (dpdk_main_t * dm, dpdk_device_t * xd) int rv; int j; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) { diff --git a/src/plugins/dpdk/device/node.c b/src/plugins/dpdk/device/node.c index e740fd18..b10e0fad 100644 --- a/src/plugins/dpdk/device/node.c +++ b/src/plugins/dpdk/device/node.c @@ -283,7 +283,7 @@ dpdk_buffer_init_from_template (void *d0, void *d1, void *d2, void *d3, */ static_always_inline u32 dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, - vlib_node_runtime_t * node, u32 cpu_index, u16 queue_id, + vlib_node_runtime_t * node, u32 thread_index, u16 queue_id, int maybe_multiseg) { u32 n_buffers; @@ -294,7 +294,7 @@ dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, uword n_rx_bytes = 0; u32 n_trace, trace_cnt __attribute__ ((unused)); vlib_buffer_free_list_t *fl; - vlib_buffer_t *bt = vec_elt_at_index (dm->buffer_templates, cpu_index); + vlib_buffer_t *bt = vec_elt_at_index (dm->buffer_templates, thread_index); if ((xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) == 0) return 0; @@ -306,7 +306,7 @@ dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, return 0; } - vec_reset_length (xd->d_trace_buffers[cpu_index]); + vec_reset_length (xd->d_trace_buffers[thread_index]); trace_cnt = n_trace = vlib_get_trace_count (vm, node); if (n_trace > 0) @@ -318,7 +318,7 @@ dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, { struct rte_mbuf *mb = xd->rx_vectors[queue_id][mb_index++]; vlib_buffer_t *b = vlib_buffer_from_rte_mbuf (mb); - vec_add1 (xd->d_trace_buffers[cpu_index], + vec_add1 (xd->d_trace_buffers[thread_index], vlib_get_buffer_index (vm, b)); } } @@ -546,20 +546,22 @@ dpdk_device_input (dpdk_main_t * dm, dpdk_device_t * xd, vlib_put_next_frame (vm, node, next_index, n_left_to_next); } - if (PREDICT_FALSE (vec_len (xd->d_trace_buffers[cpu_index]) > 0)) + if (PREDICT_FALSE (vec_len (xd->d_trace_buffers[thread_index]) > 0)) { - dpdk_rx_trace (dm, node, xd, queue_id, xd->d_trace_buffers[cpu_index], - vec_len (xd->d_trace_buffers[cpu_index])); - vlib_set_trace_count (vm, node, n_trace - - vec_len (xd->d_trace_buffers[cpu_index])); + dpdk_rx_trace (dm, node, xd, queue_id, + xd->d_trace_buffers[thread_index], + vec_len (xd->d_trace_buffers[thread_index])); + vlib_set_trace_count (vm, node, + n_trace - + vec_len (xd->d_trace_buffers[thread_index])); } vlib_increment_combined_counter (vnet_get_main ()->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, xd->vlib_sw_if_index, mb_index, n_rx_bytes); + thread_index, xd->vlib_sw_if_index, mb_index, n_rx_bytes); - vnet_device_increment_rx_packets (cpu_index, mb_index); + vnet_device_increment_rx_packets (thread_index, mb_index); return mb_index; } @@ -630,19 +632,19 @@ dpdk_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f) dpdk_device_t *xd; uword n_rx_packets = 0; dpdk_device_and_queue_t *dq; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); /* * Poll all devices on this cpu for input/interrupts. */ /* *INDENT-OFF* */ - vec_foreach (dq, dm->devices_by_cpu[cpu_index]) + vec_foreach (dq, dm->devices_by_cpu[thread_index]) { xd = vec_elt_at_index(dm->devices, dq->device); if (xd->flags & DPDK_DEVICE_FLAG_MAYBE_MULTISEG) - n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id, /* maybe_multiseg */ 1); + n_rx_packets += dpdk_device_input (dm, xd, node, thread_index, dq->queue_id, /* maybe_multiseg */ 1); else - n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id, /* maybe_multiseg */ 0); + n_rx_packets += dpdk_device_input (dm, xd, node, thread_index, dq->queue_id, /* maybe_multiseg */ 0); } /* *INDENT-ON* */ diff --git a/src/plugins/dpdk/hqos/hqos.c b/src/plugins/dpdk/hqos/hqos.c index a288fca7..8b251beb 100644 --- a/src/plugins/dpdk/hqos/hqos.c +++ b/src/plugins/dpdk/hqos/hqos.c @@ -397,7 +397,7 @@ static_always_inline void dpdk_hqos_thread_internal_hqos_dbg_bypass (vlib_main_t * vm) { dpdk_main_t *dm = &dpdk_main; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; u32 dev_pos; dev_pos = 0; @@ -405,12 +405,12 @@ dpdk_hqos_thread_internal_hqos_dbg_bypass (vlib_main_t * vm) { vlib_worker_thread_barrier_check (); - u32 n_devs = vec_len (dm->devices_by_hqos_cpu[cpu_index]); + u32 n_devs = vec_len (dm->devices_by_hqos_cpu[thread_index]); if (dev_pos >= n_devs) dev_pos = 0; dpdk_device_and_queue_t *dq = - vec_elt_at_index (dm->devices_by_hqos_cpu[cpu_index], dev_pos); + vec_elt_at_index (dm->devices_by_hqos_cpu[thread_index], dev_pos); dpdk_device_t *xd = vec_elt_at_index (dm->devices, dq->device); dpdk_device_hqos_per_hqos_thread_t *hqos = xd->hqos_ht; @@ -479,7 +479,7 @@ static_always_inline void dpdk_hqos_thread_internal (vlib_main_t * vm) { dpdk_main_t *dm = &dpdk_main; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; u32 dev_pos; dev_pos = 0; @@ -487,7 +487,7 @@ dpdk_hqos_thread_internal (vlib_main_t * vm) { vlib_worker_thread_barrier_check (); - u32 n_devs = vec_len (dm->devices_by_hqos_cpu[cpu_index]); + u32 n_devs = vec_len (dm->devices_by_hqos_cpu[thread_index]); if (PREDICT_FALSE (n_devs == 0)) { dev_pos = 0; @@ -497,7 +497,7 @@ dpdk_hqos_thread_internal (vlib_main_t * vm) dev_pos = 0; dpdk_device_and_queue_t *dq = - vec_elt_at_index (dm->devices_by_hqos_cpu[cpu_index], dev_pos); + vec_elt_at_index (dm->devices_by_hqos_cpu[thread_index], dev_pos); dpdk_device_t *xd = vec_elt_at_index (dm->devices, dq->device); dpdk_device_hqos_per_hqos_thread_t *hqos = xd->hqos_ht; @@ -586,7 +586,7 @@ dpdk_hqos_thread (vlib_worker_thread_t * w) vm = vlib_get_main (); - ASSERT (vm->cpu_index == os_get_cpu_number ()); + ASSERT (vm->thread_index == vlib_get_thread_index ()); clib_time_init (&vm->clib_time); clib_mem_set_heap (w->thread_mheap); @@ -595,7 +595,7 @@ dpdk_hqos_thread (vlib_worker_thread_t * w) while (tm->worker_thread_release == 0) vlib_worker_thread_barrier_check (); - if (vec_len (dm->devices_by_hqos_cpu[vm->cpu_index]) == 0) + if (vec_len (dm->devices_by_hqos_cpu[vm->thread_index]) == 0) return clib_error ("current I/O TX thread does not have any devices assigned to it"); diff --git a/src/plugins/dpdk/ipsec/cli.c b/src/plugins/dpdk/ipsec/cli.c index cd0a6037..3ae8c9b8 100644 --- a/src/plugins/dpdk/ipsec/cli.c +++ b/src/plugins/dpdk/ipsec/cli.c @@ -42,8 +42,8 @@ dpdk_ipsec_show_mapping (vlib_main_t * vm, u16 detail_display) for (i = 0; i < tm->n_vlib_mains; i++) { uword key, data; - u32 cpu_index = vlib_mains[i]->cpu_index; - crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + u32 thread_index = vlib_mains[i]->thread_index; + crypto_worker_main_t *cwm = &dcm->workers_main[thread_index]; u8 *s = 0; if (skip_master) @@ -57,7 +57,7 @@ dpdk_ipsec_show_mapping (vlib_main_t * vm, u16 detail_display) i32 last_cdev = -1; crypto_qp_data_t *qpd; - s = format (s, "%u\t", cpu_index); + s = format (s, "%u\t", thread_index); /* *INDENT-OFF* */ vec_foreach (qpd, cwm->qp_data) @@ -95,7 +95,7 @@ dpdk_ipsec_show_mapping (vlib_main_t * vm, u16 detail_display) cap.sym.auth.algo = p_key->auth_algo; check_algo_is_supported (&cap, auth_str); vlib_cli_output (vm, "%u\t%10s\t%15s\t%3s\t%u\t%u\n", - vlib_mains[i]->cpu_index, cipher_str, auth_str, + vlib_mains[i]->thread_index, cipher_str, auth_str, p_key->is_outbound ? "out" : "in", cwm->qp_data[data].dev_id, cwm->qp_data[data].qp_id); diff --git a/src/plugins/dpdk/ipsec/crypto_node.c b/src/plugins/dpdk/ipsec/crypto_node.c index dc3452b2..a3c45902 100644 --- a/src/plugins/dpdk/ipsec/crypto_node.c +++ b/src/plugins/dpdk/ipsec/crypto_node.c @@ -171,9 +171,9 @@ static uword dpdk_crypto_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); dpdk_crypto_main_t *dcm = &dpdk_crypto_main; - crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + crypto_worker_main_t *cwm = &dcm->workers_main[thread_index]; crypto_qp_data_t *qpd; u32 n_deq = 0; diff --git a/src/plugins/dpdk/ipsec/esp.h b/src/plugins/dpdk/ipsec/esp.h index 320295b1..56f0c756 100644 --- a/src/plugins/dpdk/ipsec/esp.h +++ b/src/plugins/dpdk/ipsec/esp.h @@ -170,9 +170,9 @@ static_always_inline int create_sym_sess (ipsec_sa_t * sa, crypto_sa_session_t * sa_sess, u8 is_outbound) { - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); dpdk_crypto_main_t *dcm = &dpdk_crypto_main; - crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + crypto_worker_main_t *cwm = &dcm->workers_main[thread_index]; struct rte_crypto_sym_xform cipher_xform = { 0 }; struct rte_crypto_sym_xform auth_xform = { 0 }; struct rte_crypto_sym_xform *xfs; diff --git a/src/plugins/dpdk/ipsec/esp_decrypt.c b/src/plugins/dpdk/ipsec/esp_decrypt.c index 286e03f8..bab76e3b 100644 --- a/src/plugins/dpdk/ipsec/esp_decrypt.c +++ b/src/plugins/dpdk/ipsec/esp_decrypt.c @@ -88,7 +88,7 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm, { u32 n_left_from, *from, *to_next, next_index; ipsec_main_t *im = &ipsec_main; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); dpdk_crypto_main_t * dcm = &dpdk_crypto_main; dpdk_esp_main_t * em = &dpdk_esp_main; u32 i; @@ -104,7 +104,7 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm, return n_left_from; } - crypto_worker_main_t *cwm = vec_elt_at_index(dcm->workers_main, cpu_index); + crypto_worker_main_t *cwm = vec_elt_at_index(dcm->workers_main, thread_index); u32 n_qps = vec_len(cwm->qp_data); struct rte_crypto_op ** cops_to_enq[n_qps]; u32 n_cop_qp[n_qps], * bi_to_enq[n_qps]; diff --git a/src/plugins/dpdk/ipsec/esp_encrypt.c b/src/plugins/dpdk/ipsec/esp_encrypt.c index 5b03de73..f996d7df 100644 --- a/src/plugins/dpdk/ipsec/esp_encrypt.c +++ b/src/plugins/dpdk/ipsec/esp_encrypt.c @@ -93,7 +93,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, { u32 n_left_from, *from, *to_next, next_index; ipsec_main_t *im = &ipsec_main; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); dpdk_crypto_main_t *dcm = &dpdk_crypto_main; dpdk_esp_main_t *em = &dpdk_esp_main; u32 i; @@ -111,7 +111,8 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, return n_left_from; } - crypto_worker_main_t *cwm = vec_elt_at_index (dcm->workers_main, cpu_index); + crypto_worker_main_t *cwm = + vec_elt_at_index (dcm->workers_main, thread_index); u32 n_qps = vec_len (cwm->qp_data); struct rte_crypto_op **cops_to_enq[n_qps]; u32 n_cop_qp[n_qps], *bi_to_enq[n_qps]; diff --git a/src/plugins/dpdk/ipsec/ipsec.c b/src/plugins/dpdk/ipsec/ipsec.c index b0aaaaec..5d8f4fba 100644 --- a/src/plugins/dpdk/ipsec/ipsec.c +++ b/src/plugins/dpdk/ipsec/ipsec.c @@ -289,7 +289,7 @@ dpdk_ipsec_process (vlib_main_t * vm, vlib_node_runtime_t * rt, if (!map) { clib_warning ("unable to create hash table for worker %u", - vlib_mains[i]->cpu_index); + vlib_mains[i]->thread_index); goto error; } cwm->algo_qp_map = map; diff --git a/src/plugins/dpdk/ipsec/ipsec.h b/src/plugins/dpdk/ipsec/ipsec.h index 28bffc80..f0f793c0 100644 --- a/src/plugins/dpdk/ipsec/ipsec.h +++ b/src/plugins/dpdk/ipsec/ipsec.h @@ -95,8 +95,8 @@ static_always_inline void crypto_alloc_cops () { dpdk_crypto_main_t *dcm = &dpdk_crypto_main; - u32 cpu_index = os_get_cpu_number (); - crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + u32 thread_index = vlib_get_thread_index (); + crypto_worker_main_t *cwm = &dcm->workers_main[thread_index]; unsigned socket_id = rte_socket_id (); crypto_qp_data_t *qpd; diff --git a/src/plugins/dpdk/main.c b/src/plugins/dpdk/main.c index 7ee2a785..942b8b2d 100644 --- a/src/plugins/dpdk/main.c +++ b/src/plugins/dpdk/main.c @@ -39,7 +39,7 @@ rte_delay_us_override (unsigned us) * thread then do not intercept. (Must not be called from an * independent pthread). */ - if (os_get_cpu_number () == 0) + if (vlib_get_thread_index () == 0) { /* * We're in the vlib main thread or a vlib process. Make sure diff --git a/src/plugins/flowperpkt/l2_node.c b/src/plugins/flowperpkt/l2_node.c index 1c2f681e..fdaf81d1 100644 --- a/src/plugins/flowperpkt/l2_node.c +++ b/src/plugins/flowperpkt/l2_node.c @@ -102,7 +102,7 @@ add_to_flow_record_l2 (vlib_main_t * vm, u8 * src_mac, u8 * dst_mac, u16 ethertype, u64 timestamp, u16 length, int do_flush) { - u32 my_cpu_number = vm->cpu_index; + u32 my_cpu_number = vm->thread_index; flow_report_main_t *frm = &flow_report_main; ip4_header_t *ip; udp_header_t *udp; diff --git a/src/plugins/flowperpkt/node.c b/src/plugins/flowperpkt/node.c index f77f087d..0277682d 100644 --- a/src/plugins/flowperpkt/node.c +++ b/src/plugins/flowperpkt/node.c @@ -101,7 +101,7 @@ add_to_flow_record_ipv4 (vlib_main_t * vm, u32 src_address, u32 dst_address, u8 tos, u64 timestamp, u16 length, int do_flush) { - u32 my_cpu_number = vm->cpu_index; + u32 my_cpu_number = vm->thread_index; flow_report_main_t *frm = &flow_report_main; ip4_header_t *ip; udp_header_t *udp; diff --git a/src/plugins/ioam/export-common/ioam_export.h b/src/plugins/ioam/export-common/ioam_export.h index 2bf3fd54..9de0d13b 100644 --- a/src/plugins/ioam/export-common/ioam_export.h +++ b/src/plugins/ioam/export-common/ioam_export.h @@ -477,8 +477,8 @@ do { \ from = vlib_frame_vector_args (F); \ n_left_from = (F)->n_vectors; \ next_index = (N)->cached_next_index; \ - while (__sync_lock_test_and_set ((EM)->lockp[(VM)->cpu_index], 1)); \ - my_buf = ioam_export_get_my_buffer (EM, (VM)->cpu_index); \ + while (__sync_lock_test_and_set ((EM)->lockp[(VM)->thread_index], 1)); \ + my_buf = ioam_export_get_my_buffer (EM, (VM)->thread_index); \ my_buf->touched_at = vlib_time_now (VM); \ while (n_left_from > 0) \ { \ @@ -620,7 +620,7 @@ do { \ } \ vlib_node_increment_counter (VM, export_node.index, \ EXPORT_ERROR_RECORDED, pkts_recorded); \ - *(EM)->lockp[(VM)->cpu_index] = 0; \ + *(EM)->lockp[(VM)->thread_index] = 0; \ } while(0) #endif /* __included_ioam_export_h__ */ diff --git a/src/plugins/ioam/ip6/ioam_cache_tunnel_select_node.c b/src/plugins/ioam/ip6/ioam_cache_tunnel_select_node.c index a56dc040..0cf742c9 100644 --- a/src/plugins/ioam/ip6/ioam_cache_tunnel_select_node.c +++ b/src/plugins/ioam/ip6/ioam_cache_tunnel_select_node.c @@ -396,7 +396,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, clib_net_to_host_u32 (tcp0->seq_number) + 1, no_of_responses, now, - vm->cpu_index, &pool_index0)) + vm->thread_index, &pool_index0)) { cache_ts_added++; } @@ -419,7 +419,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, e2e = (ioam_e2e_cache_option_t *) ((u8 *) hbh0 + cm->rewrite_pool_index_offset); - e2e->pool_id = (u8) vm->cpu_index; + e2e->pool_id = (u8) vm->thread_index; e2e->pool_index = pool_index0; ioam_e2e_id_rewrite_handler ((ioam_e2e_id_option_t *) ((u8 *) e2e + @@ -455,7 +455,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, clib_net_to_host_u32 (tcp1->seq_number) + 1, no_of_responses, now, - vm->cpu_index, &pool_index1)) + vm->thread_index, &pool_index1)) { cache_ts_added++; } @@ -479,7 +479,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, e2e = (ioam_e2e_cache_option_t *) ((u8 *) hbh1 + cm->rewrite_pool_index_offset); - e2e->pool_id = (u8) vm->cpu_index; + e2e->pool_id = (u8) vm->thread_index; e2e->pool_index = pool_index1; ioam_e2e_id_rewrite_handler ((ioam_e2e_id_option_t *) ((u8 *) e2e + @@ -562,7 +562,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, clib_net_to_host_u32 (tcp0->seq_number) + 1, no_of_responses, now, - vm->cpu_index, &pool_index0)) + vm->thread_index, &pool_index0)) { cache_ts_added++; } @@ -585,7 +585,7 @@ ip6_reset_ts_hbh_node_fn (vlib_main_t * vm, e2e = (ioam_e2e_cache_option_t *) ((u8 *) hbh0 + cm->rewrite_pool_index_offset); - e2e->pool_id = (u8) vm->cpu_index; + e2e->pool_id = (u8) vm->thread_index; e2e->pool_index = pool_index0; ioam_e2e_id_rewrite_handler ((ioam_e2e_id_option_t *) ((u8 *) e2e + @@ -701,7 +701,7 @@ expired_cache_ts_timer_callback (u32 * expired_timers) ioam_cache_main_t *cm = &ioam_cache_main; int i; u32 pool_index; - u32 thread_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 count = 0; for (i = 0; i < vec_len (expired_timers); i++) @@ -724,7 +724,7 @@ ioam_cache_ts_timer_tick_node_fn (vlib_main_t * vm, vlib_frame_t * f) { ioam_cache_main_t *cm = &ioam_cache_main; - u32 my_thread_index = os_get_cpu_number (); + u32 my_thread_index = vlib_get_thread_index (); struct timespec ts, tsrem; tw_timer_expire_timers_16t_2w_512sl (&cm->timer_wheels[my_thread_index], diff --git a/src/plugins/ixge/ixge.c b/src/plugins/ixge/ixge.c index f3c5cc09..08f5b692 100644 --- a/src/plugins/ixge/ixge.c +++ b/src/plugins/ixge/ixge.c @@ -1887,7 +1887,7 @@ done: vlib_increment_combined_counter (vnet_main. interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - 0 /* cpu_index */ , + 0 /* thread_index */ , xd->vlib_sw_if_index, n_packets, dq->rx.n_bytes); diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index add81236..addc2a42 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -63,11 +63,11 @@ u8 *format_lb_main (u8 * s, va_list * args) s = format(s, " #vips: %u\n", pool_elts(lbm->vips)); s = format(s, " #ass: %u\n", pool_elts(lbm->ass) - 1); - u32 cpu_index; - for(cpu_index = 0; cpu_index < tm->n_vlib_mains; cpu_index++ ) { - lb_hash_t *h = lbm->per_cpu[cpu_index].sticky_ht; + u32 thread_index; + for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) { + lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht; if (h) { - s = format(s, "core %d\n", cpu_index); + s = format(s, "core %d\n", thread_index); s = format(s, " timeout: %ds\n", h->timeout); s = format(s, " usage: %d / %d\n", lb_hash_elts(h, lb_hash_time_now(vlib_get_main())), lb_hash_size(h)); } diff --git a/src/plugins/lb/node.c b/src/plugins/lb/node.c index 8b763c53..3171148b 100644 --- a/src/plugins/lb/node.c +++ b/src/plugins/lb/node.c @@ -60,10 +60,10 @@ format_lb_trace (u8 * s, va_list * args) return s; } -lb_hash_t *lb_get_sticky_table(u32 cpu_index) +lb_hash_t *lb_get_sticky_table(u32 thread_index) { lb_main_t *lbm = &lb_main; - lb_hash_t *sticky_ht = lbm->per_cpu[cpu_index].sticky_ht; + lb_hash_t *sticky_ht = lbm->per_cpu[thread_index].sticky_ht; //Check if size changed if (PREDICT_FALSE(sticky_ht && (lbm->per_cpu_sticky_buckets != lb_hash_nbuckets(sticky_ht)))) { @@ -71,8 +71,8 @@ lb_hash_t *lb_get_sticky_table(u32 cpu_index) lb_hash_bucket_t *b; u32 i; lb_hash_foreach_entry(sticky_ht, b, i) { - vlib_refcount_add(&lbm->as_refcount, cpu_index, b->value[i], -1); - vlib_refcount_add(&lbm->as_refcount, cpu_index, 0, 1); + vlib_refcount_add(&lbm->as_refcount, thread_index, b->value[i], -1); + vlib_refcount_add(&lbm->as_refcount, thread_index, 0, 1); } lb_hash_free(sticky_ht); @@ -81,8 +81,8 @@ lb_hash_t *lb_get_sticky_table(u32 cpu_index) //Create if necessary if (PREDICT_FALSE(sticky_ht == NULL)) { - lbm->per_cpu[cpu_index].sticky_ht = lb_hash_alloc(lbm->per_cpu_sticky_buckets, lbm->flow_timeout); - sticky_ht = lbm->per_cpu[cpu_index].sticky_ht; + lbm->per_cpu[thread_index].sticky_ht = lb_hash_alloc(lbm->per_cpu_sticky_buckets, lbm->flow_timeout); + sticky_ht = lbm->per_cpu[thread_index].sticky_ht; clib_warning("Regenerated sticky table %p", sticky_ht); } @@ -153,10 +153,10 @@ lb_node_fn (vlib_main_t * vm, { lb_main_t *lbm = &lb_main; u32 n_left_from, *from, next_index, *to_next, n_left_to_next; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u32 lb_time = lb_hash_time_now(vm); - lb_hash_t *sticky_ht = lb_get_sticky_table(cpu_index); + lb_hash_t *sticky_ht = lb_get_sticky_table(thread_index); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -240,9 +240,9 @@ lb_node_fn (vlib_main_t * vm, //Configuration may be changed, vectors resized, etc... //Dereference previously used - vlib_refcount_add(&lbm->as_refcount, cpu_index, + vlib_refcount_add(&lbm->as_refcount, thread_index, lb_hash_available_value(sticky_ht, hash0, available_index0), -1); - vlib_refcount_add(&lbm->as_refcount, cpu_index, + vlib_refcount_add(&lbm->as_refcount, thread_index, asindex0, 1); //Add sticky entry @@ -260,7 +260,7 @@ lb_node_fn (vlib_main_t * vm, } vlib_increment_simple_counter(&lbm->vip_counters[counter], - cpu_index, + thread_index, vnet_buffer (p0)->ip.adj_index[VLIB_TX], 1); diff --git a/src/plugins/lb/refcount.c b/src/plugins/lb/refcount.c index 22415c88..6f01ab5a 100644 --- a/src/plugins/lb/refcount.c +++ b/src/plugins/lb/refcount.c @@ -31,10 +31,10 @@ u64 vlib_refcount_get(vlib_refcount_t *r, u32 index) { u64 count = 0; vlib_thread_main_t *tm = vlib_get_thread_main (); - u32 cpu_index; - for (cpu_index = 0; cpu_index < tm->n_vlib_mains; cpu_index++) { - if (r->per_cpu[cpu_index].length > index) - count += r->per_cpu[cpu_index].counters[index]; + u32 thread_index; + for (thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++) { + if (r->per_cpu[thread_index].length > index) + count += r->per_cpu[thread_index].counters[index]; } return count; } diff --git a/src/plugins/lb/refcount.h b/src/plugins/lb/refcount.h index 8c26e7be..dcfcb3fe 100644 --- a/src/plugins/lb/refcount.h +++ b/src/plugins/lb/refcount.h @@ -45,9 +45,9 @@ typedef struct { void __vlib_refcount_resize(vlib_refcount_per_cpu_t *per_cpu, u32 size); static_always_inline -void vlib_refcount_add(vlib_refcount_t *r, u32 cpu_index, u32 counter_index, i32 v) +void vlib_refcount_add(vlib_refcount_t *r, u32 thread_index, u32 counter_index, i32 v) { - vlib_refcount_per_cpu_t *per_cpu = &r->per_cpu[cpu_index]; + vlib_refcount_per_cpu_t *per_cpu = &r->per_cpu[thread_index]; if (PREDICT_FALSE(counter_index >= per_cpu->length)) __vlib_refcount_resize(per_cpu, clib_max(counter_index + 16, per_cpu->length * 2)); diff --git a/src/plugins/memif/node.c b/src/plugins/memif/node.c index 659d5dfb..cee1f3d1 100644 --- a/src/plugins/memif/node.c +++ b/src/plugins/memif/node.c @@ -94,7 +94,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, u32 n_rx_bytes = 0; u32 *to_next = 0; u32 n_free_bufs; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 bi0, bi1; vlib_buffer_t *b0, *b1; u16 ring_size = 1 << mif->log2_ring_size; @@ -105,14 +105,15 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (mif->per_interface_next_index != ~0) next_index = mif->per_interface_next_index; - n_free_bufs = vec_len (nm->rx_buffers[cpu_index]); + n_free_bufs = vec_len (nm->rx_buffers[thread_index]); if (PREDICT_FALSE (n_free_bufs < ring_size)) { - vec_validate (nm->rx_buffers[cpu_index], ring_size + n_free_bufs - 1); + vec_validate (nm->rx_buffers[thread_index], + ring_size + n_free_bufs - 1); n_free_bufs += - vlib_buffer_alloc (vm, &nm->rx_buffers[cpu_index][n_free_bufs], + vlib_buffer_alloc (vm, &nm->rx_buffers[thread_index][n_free_bufs], ring_size); - _vec_len (nm->rx_buffers[cpu_index]) = n_free_bufs; + _vec_len (nm->rx_buffers[thread_index]) = n_free_bufs; } head = ring->head; @@ -158,15 +159,15 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, CLIB_CACHE_LINE_BYTES, LOAD); } /* get empty buffer */ - u32 last_buf = vec_len (nm->rx_buffers[cpu_index]) - 1; - bi0 = nm->rx_buffers[cpu_index][last_buf]; - bi1 = nm->rx_buffers[cpu_index][last_buf - 1]; - _vec_len (nm->rx_buffers[cpu_index]) -= 2; + u32 last_buf = vec_len (nm->rx_buffers[thread_index]) - 1; + bi0 = nm->rx_buffers[thread_index][last_buf]; + bi1 = nm->rx_buffers[thread_index][last_buf - 1]; + _vec_len (nm->rx_buffers[thread_index]) -= 2; if (last_buf > 4) { - memif_prefetch (vm, nm->rx_buffers[cpu_index][last_buf - 2]); - memif_prefetch (vm, nm->rx_buffers[cpu_index][last_buf - 3]); + memif_prefetch (vm, nm->rx_buffers[thread_index][last_buf - 2]); + memif_prefetch (vm, nm->rx_buffers[thread_index][last_buf - 3]); } /* enqueue buffer */ @@ -256,9 +257,9 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, while (num_slots && n_left_to_next) { /* get empty buffer */ - u32 last_buf = vec_len (nm->rx_buffers[cpu_index]) - 1; - bi0 = nm->rx_buffers[cpu_index][last_buf]; - _vec_len (nm->rx_buffers[cpu_index]) = last_buf; + u32 last_buf = vec_len (nm->rx_buffers[thread_index]) - 1; + bi0 = nm->rx_buffers[thread_index][last_buf]; + _vec_len (nm->rx_buffers[thread_index]) = last_buf; /* enqueue buffer */ to_next[0] = bi0; @@ -315,7 +316,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, ring->tail = head; vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters - + VNET_INTERFACE_COUNTER_RX, cpu_index, + + VNET_INTERFACE_COUNTER_RX, thread_index, mif->hw_if_index, n_rx_packets, n_rx_bytes); @@ -327,7 +328,7 @@ memif_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_rx_packets = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); memif_main_t *nm = &memif_main; memif_if_t *mif; @@ -337,7 +338,7 @@ memif_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, if (mif->flags & MEMIF_IF_FLAG_ADMIN_UP && mif->flags & MEMIF_IF_FLAG_CONNECTED && (mif->if_index % nm->input_cpu_count) == - (cpu_index - nm->input_cpu_first_index)) + (thread_index - nm->input_cpu_first_index)) { if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) n_rx_packets += diff --git a/src/plugins/snat/in2out.c b/src/plugins/snat/in2out.c index b4961365..e5ee965f 100644 --- a/src/plugins/snat/in2out.c +++ b/src/plugins/snat/in2out.c @@ -212,7 +212,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, snat_session_t ** sessionp, vlib_node_runtime_t * node, u32 next0, - u32 cpu_index) + u32 thread_index) { snat_user_t *u; snat_user_key_t user_key; @@ -246,27 +246,27 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, if (clib_bihash_search_8_8 (&sm->user_hash, &kv0, &value0)) { /* no, make a new one */ - pool_get (sm->per_thread_data[cpu_index].users, u); + pool_get (sm->per_thread_data[thread_index].users, u); memset (u, 0, sizeof (*u)); u->addr = ip0->src_address; u->fib_index = rx_fib_index0; - pool_get (sm->per_thread_data[cpu_index].list_pool, per_user_list_head_elt); + pool_get (sm->per_thread_data[thread_index].list_pool, per_user_list_head_elt); u->sessions_per_user_list_head_index = per_user_list_head_elt - - sm->per_thread_data[cpu_index].list_pool; + sm->per_thread_data[thread_index].list_pool; - clib_dlist_init (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_init (sm->per_thread_data[thread_index].list_pool, u->sessions_per_user_list_head_index); - kv0.value = u - sm->per_thread_data[cpu_index].users; + kv0.value = u - sm->per_thread_data[thread_index].users; /* add user */ clib_bihash_add_del_8_8 (&sm->user_hash, &kv0, 1 /* is_add */); } else { - u = pool_elt_at_index (sm->per_thread_data[cpu_index].users, + u = pool_elt_at_index (sm->per_thread_data[thread_index].users, value0.value); } @@ -276,25 +276,25 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, /* Remove the oldest dynamic translation */ do { oldest_per_user_translation_list_index = - clib_dlist_remove_head (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove_head (sm->per_thread_data[thread_index].list_pool, u->sessions_per_user_list_head_index); ASSERT (oldest_per_user_translation_list_index != ~0); /* add it back to the end of the LRU list */ - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, u->sessions_per_user_list_head_index, oldest_per_user_translation_list_index); /* Get the list element */ oldest_per_user_translation_list_elt = - pool_elt_at_index (sm->per_thread_data[cpu_index].list_pool, + pool_elt_at_index (sm->per_thread_data[thread_index].list_pool, oldest_per_user_translation_list_index); /* Get the session index from the list element */ session_index = oldest_per_user_translation_list_elt->value; /* Get the session */ - s = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, session_index); } while (snat_is_session_static (s)); @@ -346,7 +346,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, } /* Create a new session */ - pool_get (sm->per_thread_data[cpu_index].sessions, s); + pool_get (sm->per_thread_data[thread_index].sessions, s); memset (s, 0, sizeof (*s)); s->outside_address_index = address_index; @@ -362,22 +362,22 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, } /* Create list elts */ - pool_get (sm->per_thread_data[cpu_index].list_pool, + pool_get (sm->per_thread_data[thread_index].list_pool, per_user_translation_list_elt); - clib_dlist_init (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_init (sm->per_thread_data[thread_index].list_pool, per_user_translation_list_elt - - sm->per_thread_data[cpu_index].list_pool); + sm->per_thread_data[thread_index].list_pool); per_user_translation_list_elt->value = - s - sm->per_thread_data[cpu_index].sessions; + s - sm->per_thread_data[thread_index].sessions; s->per_user_index = per_user_translation_list_elt - - sm->per_thread_data[cpu_index].list_pool; + sm->per_thread_data[thread_index].list_pool; s->per_user_list_head_index = u->sessions_per_user_list_head_index; - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s->per_user_list_head_index, per_user_translation_list_elt - - sm->per_thread_data[cpu_index].list_pool); + sm->per_thread_data[thread_index].list_pool); } s->in2out = *key0; @@ -388,12 +388,12 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, /* Add to translation hashes */ kv0.key = s->in2out.as_u64; - kv0.value = s - sm->per_thread_data[cpu_index].sessions; + kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 1 /* is_add */)) clib_warning ("in2out key add failed"); kv0.key = s->out2in.as_u64; - kv0.value = s - sm->per_thread_data[cpu_index].sessions; + kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 1 /* is_add */)) clib_warning ("out2in key add failed"); @@ -403,7 +403,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, worker_by_out_key.port = s->out2in.port; worker_by_out_key.fib_index = s->out2in.fib_index; kv0.key = worker_by_out_key.as_u64; - kv0.value = cpu_index; + kv0.value = thread_index; clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1); /* log NAT event */ @@ -465,7 +465,7 @@ snat_in2out_error_t icmp_get_key(icmp46_header_t *icmp0, * * @param[in,out] sm SNAT main * @param[in,out] node SNAT node runtime - * @param[in] cpu_index CPU index + * @param[in] thread_index thread index * @param[in,out] b0 buffer containing packet to be translated * @param[out] p_key address and port before NAT translation * @param[out] p_value address and port after NAT translation @@ -473,7 +473,7 @@ snat_in2out_error_t icmp_get_key(icmp46_header_t *icmp0, * @param d optional parameter */ u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d) @@ -524,13 +524,13 @@ u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, } next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0, - &s0, node, next0, cpu_index); + &s0, node, next0, thread_index); if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP)) goto out; } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); out: @@ -548,7 +548,7 @@ out: * * @param[in] sm SNAT main * @param[in,out] node SNAT node runtime - * @param[in] cpu_index CPU index + * @param[in] thread_index thread index * @param[in,out] b0 buffer containing packet to be translated * @param[out] p_key address and port before NAT translation * @param[out] p_value address and port after NAT translation @@ -556,7 +556,7 @@ out: * @param d optional parameter */ u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d) @@ -624,7 +624,7 @@ static inline u32 icmp_in2out (snat_main_t *sm, u32 rx_fib_index0, vlib_node_runtime_t * node, u32 next0, - u32 cpu_index, + u32 thread_index, void *d) { snat_session_key_t key0, sm0; @@ -641,7 +641,7 @@ static inline u32 icmp_in2out (snat_main_t *sm, echo0 = (icmp_echo_header_t *)(icmp0+1); - next0_tmp = sm->icmp_match_in2out_cb(sm, node, cpu_index, b0, + next0_tmp = sm->icmp_match_in2out_cb(sm, node, thread_index, b0, &key0, &sm0, &dont_translate, d); if (next0_tmp != ~0) next0 = next0_tmp; @@ -847,11 +847,11 @@ static inline u32 icmp_in2out_slow_path (snat_main_t *sm, vlib_node_runtime_t * node, u32 next0, f64 now, - u32 cpu_index, + u32 thread_index, snat_session_t ** p_s0) { next0 = icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, - next0, cpu_index, p_s0); + next0, thread_index, p_s0); snat_session_t * s0 = *p_s0; if (PREDICT_TRUE(next0 != SNAT_IN2OUT_NEXT_DROP && s0)) { @@ -862,9 +862,9 @@ static inline u32 icmp_in2out_slow_path (snat_main_t *sm, /* Per-user LRU list maintenance for dynamic translations */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -884,7 +884,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, snat_runtime_t * rt = (snat_runtime_t *)node->runtime_data; f64 now = vlib_time_now (vm); u32 stats_node_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); stats_node_index = is_slow_path ? snat_in2out_slowpath_node.index : snat_in2out_node.index; @@ -977,7 +977,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { next0 = icmp_in2out_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, - node, next0, now, cpu_index, &s0); + node, next0, now, thread_index, &s0); goto trace00; } } @@ -1006,7 +1006,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, goto trace00; next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0, - &s0, node, next0, cpu_index); + &s0, node, next0, thread_index); if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP)) goto trace00; } @@ -1017,7 +1017,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); old_addr0 = ip0->src_address.as_u32; @@ -1063,9 +1063,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -1081,7 +1081,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, t->next_index = next0; t->session_index = ~0; if (s0) - t->session_index = s0 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s0 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP; @@ -1117,7 +1117,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { next1 = icmp_in2out_slow_path (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node, - next1, now, cpu_index, &s1); + next1, now, thread_index, &s1); goto trace01; } } @@ -1146,7 +1146,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, goto trace01; next1 = slow_path (sm, b1, ip1, rx_fib_index1, &key1, - &s1, node, next1, cpu_index); + &s1, node, next1, thread_index); if (PREDICT_FALSE (next1 == SNAT_IN2OUT_NEXT_DROP)) goto trace01; } @@ -1157,7 +1157,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } } else - s1 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s1 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value1.value); old_addr1 = ip1->src_address.as_u32; @@ -1203,9 +1203,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s1)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s1->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s1->per_user_list_head_index, s1->per_user_index); } @@ -1220,7 +1220,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, t->next_index = next1; t->session_index = ~0; if (s1) - t->session_index = s1 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s1 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next1 != SNAT_IN2OUT_NEXT_DROP; @@ -1292,7 +1292,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { next0 = icmp_in2out_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, - next0, now, cpu_index, &s0); + next0, now, thread_index, &s0); goto trace0; } } @@ -1321,7 +1321,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, goto trace0; next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0, - &s0, node, next0, cpu_index); + &s0, node, next0, thread_index); if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP)) goto trace0; @@ -1333,7 +1333,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); old_addr0 = ip0->src_address.as_u32; @@ -1379,9 +1379,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -1397,7 +1397,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, t->next_index = next0; t->session_index = ~0; if (s0) - t->session_index = s0 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s0 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP; @@ -2010,7 +2010,7 @@ snat_in2out_worker_handoff_fn (vlib_main_t * vm, u32 n_left_to_next_worker = 0, *to_next_worker = 0; u32 next_worker_index = 0; u32 current_worker_index = ~0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); ASSERT (vec_len (sm->workers)); @@ -2048,7 +2048,7 @@ snat_in2out_worker_handoff_fn (vlib_main_t * vm, next_worker_index = sm->worker_in2out_cb(ip0, rx_fib_index0); - if (PREDICT_FALSE (next_worker_index != cpu_index)) + if (PREDICT_FALSE (next_worker_index != thread_index)) { do_handoff = 1; diff --git a/src/plugins/snat/out2in.c b/src/plugins/snat/out2in.c index 656e42db..5d308d78 100644 --- a/src/plugins/snat/out2in.c +++ b/src/plugins/snat/out2in.c @@ -129,7 +129,7 @@ create_session_for_static_mapping (snat_main_t *sm, snat_session_key_t in2out, snat_session_key_t out2in, vlib_node_runtime_t * node, - u32 cpu_index) + u32 thread_index) { snat_user_t *u; snat_user_key_t user_key; @@ -146,36 +146,36 @@ create_session_for_static_mapping (snat_main_t *sm, if (clib_bihash_search_8_8 (&sm->user_hash, &kv0, &value0)) { /* no, make a new one */ - pool_get (sm->per_thread_data[cpu_index].users, u); + pool_get (sm->per_thread_data[thread_index].users, u); memset (u, 0, sizeof (*u)); u->addr = in2out.addr; u->fib_index = in2out.fib_index; - pool_get (sm->per_thread_data[cpu_index].list_pool, + pool_get (sm->per_thread_data[thread_index].list_pool, per_user_list_head_elt); u->sessions_per_user_list_head_index = per_user_list_head_elt - - sm->per_thread_data[cpu_index].list_pool; + sm->per_thread_data[thread_index].list_pool; - clib_dlist_init (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_init (sm->per_thread_data[thread_index].list_pool, u->sessions_per_user_list_head_index); - kv0.value = u - sm->per_thread_data[cpu_index].users; + kv0.value = u - sm->per_thread_data[thread_index].users; /* add user */ clib_bihash_add_del_8_8 (&sm->user_hash, &kv0, 1 /* is_add */); /* add non-traslated packets worker lookup */ - kv0.value = cpu_index; + kv0.value = thread_index; clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv0, 1); } else { - u = pool_elt_at_index (sm->per_thread_data[cpu_index].users, + u = pool_elt_at_index (sm->per_thread_data[thread_index].users, value0.value); } - pool_get (sm->per_thread_data[cpu_index].sessions, s); + pool_get (sm->per_thread_data[thread_index].sessions, s); memset (s, 0, sizeof (*s)); s->outside_address_index = ~0; @@ -183,22 +183,22 @@ create_session_for_static_mapping (snat_main_t *sm, u->nstaticsessions++; /* Create list elts */ - pool_get (sm->per_thread_data[cpu_index].list_pool, + pool_get (sm->per_thread_data[thread_index].list_pool, per_user_translation_list_elt); - clib_dlist_init (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_init (sm->per_thread_data[thread_index].list_pool, per_user_translation_list_elt - - sm->per_thread_data[cpu_index].list_pool); + sm->per_thread_data[thread_index].list_pool); per_user_translation_list_elt->value = - s - sm->per_thread_data[cpu_index].sessions; + s - sm->per_thread_data[thread_index].sessions; s->per_user_index = - per_user_translation_list_elt - sm->per_thread_data[cpu_index].list_pool; + per_user_translation_list_elt - sm->per_thread_data[thread_index].list_pool; s->per_user_list_head_index = u->sessions_per_user_list_head_index; - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s->per_user_list_head_index, per_user_translation_list_elt - - sm->per_thread_data[cpu_index].list_pool); + sm->per_thread_data[thread_index].list_pool); s->in2out = in2out; s->out2in = out2in; @@ -206,12 +206,12 @@ create_session_for_static_mapping (snat_main_t *sm, /* Add to translation hashes */ kv0.key = s->in2out.as_u64; - kv0.value = s - sm->per_thread_data[cpu_index].sessions; + kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 1 /* is_add */)) clib_warning ("in2out key add failed"); kv0.key = s->out2in.as_u64; - kv0.value = s - sm->per_thread_data[cpu_index].sessions; + kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 1 /* is_add */)) clib_warning ("out2in key add failed"); @@ -298,7 +298,7 @@ is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, * * @param[in,out] sm SNAT main * @param[in,out] node SNAT node runtime - * @param[in] cpu_index CPU index + * @param[in] thread_index thread index * @param[in,out] b0 buffer containing packet to be translated * @param[out] p_key address and port before NAT translation * @param[out] p_value address and port after NAT translation @@ -306,7 +306,7 @@ is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, * @param d optional parameter */ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d) @@ -366,7 +366,7 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, /* Create session initiated by host from external network */ s0 = create_session_for_static_mapping(sm, b0, sm0, key0, - node, cpu_index); + node, thread_index); if (!s0) { @@ -375,7 +375,7 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); out: @@ -393,7 +393,7 @@ out: * * @param[in] sm SNAT main * @param[in,out] node SNAT node runtime - * @param[in] cpu_index CPU index + * @param[in] thread_index thread index * @param[in,out] b0 buffer containing packet to be translated * @param[out] p_key address and port before NAT translation * @param[out] p_value address and port after NAT translation @@ -401,7 +401,7 @@ out: * @param d optional parameter */ u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d) @@ -460,7 +460,7 @@ static inline u32 icmp_out2in (snat_main_t *sm, u32 rx_fib_index0, vlib_node_runtime_t * node, u32 next0, - u32 cpu_index, + u32 thread_index, void *d) { snat_session_key_t key0, sm0; @@ -477,7 +477,7 @@ static inline u32 icmp_out2in (snat_main_t *sm, echo0 = (icmp_echo_header_t *)(icmp0+1); - next0_tmp = sm->icmp_match_out2in_cb(sm, node, cpu_index, b0, + next0_tmp = sm->icmp_match_out2in_cb(sm, node, thread_index, b0, &key0, &sm0, &dont_translate, d); if (next0_tmp != ~0) next0 = next0_tmp; @@ -589,11 +589,11 @@ static inline u32 icmp_out2in_slow_path (snat_main_t *sm, u32 rx_fib_index0, vlib_node_runtime_t * node, u32 next0, f64 now, - u32 cpu_index, + u32 thread_index, snat_session_t ** p_s0) { next0 = icmp_out2in(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, - next0, cpu_index, p_s0); + next0, thread_index, p_s0); snat_session_t * s0 = *p_s0; if (PREDICT_TRUE(next0 != SNAT_OUT2IN_NEXT_DROP && s0)) { @@ -604,9 +604,9 @@ static inline u32 icmp_out2in_slow_path (snat_main_t *sm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -624,7 +624,7 @@ snat_out2in_node_fn (vlib_main_t * vm, u32 pkts_processed = 0; snat_main_t * sm = &snat_main; f64 now = vlib_time_now (vm); - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -712,7 +712,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { next0 = icmp_out2in_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, - next0, now, cpu_index, &s0); + next0, now, thread_index, &s0); goto trace0; } @@ -743,7 +743,7 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Create session initiated by host from external network */ s0 = create_session_for_static_mapping(sm, b0, sm0, key0, node, - cpu_index); + thread_index); if (!s0) { b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; @@ -752,7 +752,7 @@ snat_out2in_node_fn (vlib_main_t * vm, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); old_addr0 = ip0->dst_address.as_u32; @@ -796,9 +796,9 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -813,7 +813,7 @@ snat_out2in_node_fn (vlib_main_t * vm, t->next_index = next0; t->session_index = ~0; if (s0) - t->session_index = s0 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s0 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP; @@ -847,7 +847,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { next1 = icmp_out2in_slow_path (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node, - next1, now, cpu_index, &s1); + next1, now, thread_index, &s1); goto trace1; } @@ -878,7 +878,7 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Create session initiated by host from external network */ s1 = create_session_for_static_mapping(sm, b1, sm1, key1, node, - cpu_index); + thread_index); if (!s1) { b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; @@ -887,7 +887,7 @@ snat_out2in_node_fn (vlib_main_t * vm, } } else - s1 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s1 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value1.value); old_addr1 = ip1->dst_address.as_u32; @@ -931,9 +931,9 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s1)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s1->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s1->per_user_list_head_index, s1->per_user_index); } @@ -948,7 +948,7 @@ snat_out2in_node_fn (vlib_main_t * vm, t->next_index = next1; t->session_index = ~0; if (s1) - t->session_index = s1 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s1 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next1 != SNAT_OUT2IN_NEXT_DROP; @@ -1016,7 +1016,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { next0 = icmp_out2in_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, - next0, now, cpu_index, &s0); + next0, now, thread_index, &s0); goto trace00; } @@ -1048,7 +1048,7 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Create session initiated by host from external network */ s0 = create_session_for_static_mapping(sm, b0, sm0, key0, node, - cpu_index); + thread_index); if (!s0) { b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; @@ -1057,7 +1057,7 @@ snat_out2in_node_fn (vlib_main_t * vm, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value0.value); old_addr0 = ip0->dst_address.as_u32; @@ -1101,9 +1101,9 @@ snat_out2in_node_fn (vlib_main_t * vm, /* Per-user LRU list maintenance for dynamic translation */ if (!snat_is_session_static (s0)) { - clib_dlist_remove (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[cpu_index].list_pool, + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, s0->per_user_list_head_index, s0->per_user_index); } @@ -1118,7 +1118,7 @@ snat_out2in_node_fn (vlib_main_t * vm, t->next_index = next0; t->session_index = ~0; if (s0) - t->session_index = s0 - sm->per_thread_data[cpu_index].sessions; + t->session_index = s0 - sm->per_thread_data[thread_index].sessions; } pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP; @@ -1599,7 +1599,7 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm, u32 n_left_to_next_worker = 0, *to_next_worker = 0; u32 next_worker_index = 0; u32 current_worker_index = ~0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); ASSERT (vec_len (sm->workers)); @@ -1637,7 +1637,7 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm, next_worker_index = sm->worker_out2in_cb(ip0, rx_fib_index0); - if (PREDICT_FALSE (next_worker_index != cpu_index)) + if (PREDICT_FALSE (next_worker_index != thread_index)) { do_handoff = 1; diff --git a/src/plugins/snat/snat.h b/src/plugins/snat/snat.h index 017825c0..f4e1c5c0 100644 --- a/src/plugins/snat/snat.h +++ b/src/plugins/snat/snat.h @@ -221,7 +221,7 @@ struct snat_main_s; typedef u32 snat_icmp_match_function_t (struct snat_main_s *sm, vlib_node_runtime_t *node, - u32 cpu_index, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, @@ -402,22 +402,22 @@ typedef struct { } tcp_udp_header_t; u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d); u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d); u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d); u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, - u32 cpu_index, vlib_buffer_t *b0, + u32 thread_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d); diff --git a/src/vlib/buffer.c b/src/vlib/buffer.c index a517a597..be3b41ef 100644 --- a/src/vlib/buffer.c +++ b/src/vlib/buffer.c @@ -299,7 +299,7 @@ vlib_buffer_validate_alloc_free (vlib_main_t * vm, if (CLIB_DEBUG == 0) return; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); /* smp disaster check */ if (vec_len (vlib_mains) > 1) @@ -355,7 +355,7 @@ vlib_buffer_create_free_list_helper (vlib_main_t * vm, vlib_buffer_free_list_t *f; int i; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0) { @@ -474,7 +474,7 @@ vlib_buffer_delete_free_list_internal (vlib_main_t * vm, u32 free_list_index) u32 merge_index; int i; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); f = vlib_buffer_get_free_list (vm, free_list_index); diff --git a/src/vlib/buffer_funcs.h b/src/vlib/buffer_funcs.h index 394c336a..328660a3 100644 --- a/src/vlib/buffer_funcs.h +++ b/src/vlib/buffer_funcs.h @@ -209,7 +209,7 @@ always_inline vlib_buffer_known_state_t vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index) { vlib_buffer_main_t *bm = vm->buffer_main; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); uword *p = hash_get (bm->buffer_known_hash, buffer_index); return p ? p[0] : VLIB_BUFFER_UNKNOWN; @@ -221,7 +221,7 @@ vlib_buffer_set_known_state (vlib_main_t * vm, vlib_buffer_known_state_t state) { vlib_buffer_main_t *bm = vm->buffer_main; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); hash_set (bm->buffer_known_hash, buffer_index, state); } diff --git a/src/vlib/cli.c b/src/vlib/cli.c index f853f655..3cc95076 100644 --- a/src/vlib/cli.c +++ b/src/vlib/cli.c @@ -709,7 +709,7 @@ test_heap_validate (vlib_main_t * vm, unformat_input_t * input, { /* *INDENT-OFF* */ foreach_vlib_main({ - heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index]; + heap = clib_per_cpu_mheaps[this_vlib_main->thread_index]; mheap = mheap_header(heap); mheap->flags |= MHEAP_FLAG_VALIDATE; // Turn off small object cache because it delays detection of errors @@ -722,7 +722,7 @@ test_heap_validate (vlib_main_t * vm, unformat_input_t * input, { /* *INDENT-OFF* */ foreach_vlib_main({ - heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index]; + heap = clib_per_cpu_mheaps[this_vlib_main->thread_index]; mheap = mheap_header(heap); mheap->flags &= ~MHEAP_FLAG_VALIDATE; mheap->flags |= MHEAP_FLAG_SMALL_OBJECT_CACHE; @@ -733,7 +733,7 @@ test_heap_validate (vlib_main_t * vm, unformat_input_t * input, { /* *INDENT-OFF* */ foreach_vlib_main({ - heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index]; + heap = clib_per_cpu_mheaps[this_vlib_main->thread_index]; mheap = mheap_header(heap); mheap_validate(heap); }); diff --git a/src/vlib/counter.h b/src/vlib/counter.h index 17a85217..60e2055d 100644 --- a/src/vlib/counter.h +++ b/src/vlib/counter.h @@ -70,17 +70,17 @@ u32 vlib_simple_counter_n_counters (const vlib_simple_counter_main_t * cm); /** Increment a simple counter @param cm - (vlib_simple_counter_main_t *) simple counter main pointer - @param cpu_index - (u32) the current cpu index + @param thread_index - (u32) the current cpu index @param index - (u32) index of the counter to increment @param increment - (u64) quantitiy to add to the counter */ always_inline void vlib_increment_simple_counter (vlib_simple_counter_main_t * cm, - u32 cpu_index, u32 index, u64 increment) + u32 thread_index, u32 index, u64 increment) { counter_t *my_counters; - my_counters = cm->counters[cpu_index]; + my_counters = cm->counters[thread_index]; my_counters[index] += increment; } @@ -201,7 +201,7 @@ void vlib_clear_combined_counters (vlib_combined_counter_main_t * cm); /** Increment a combined counter @param cm - (vlib_combined_counter_main_t *) comined counter main pointer - @param cpu_index - (u32) the current cpu index + @param thread_index - (u32) the current cpu index @param index - (u32) index of the counter to increment @param packet_increment - (u64) number of packets to add to the counter @param byte_increment - (u64) number of bytes to add to the counter @@ -209,13 +209,13 @@ void vlib_clear_combined_counters (vlib_combined_counter_main_t * cm); always_inline void vlib_increment_combined_counter (vlib_combined_counter_main_t * cm, - u32 cpu_index, + u32 thread_index, u32 index, u64 n_packets, u64 n_bytes) { vlib_counter_t *my_counters; /* Use this CPU's counter array */ - my_counters = cm->counters[cpu_index]; + my_counters = cm->counters[thread_index]; my_counters[index].packets += n_packets; my_counters[index].bytes += n_bytes; @@ -224,14 +224,14 @@ vlib_increment_combined_counter (vlib_combined_counter_main_t * cm, /** Pre-fetch a per-thread combined counter for the given object index */ always_inline void vlib_prefetch_combined_counter (const vlib_combined_counter_main_t * cm, - u32 cpu_index, u32 index) + u32 thread_index, u32 index) { vlib_counter_t *cpu_counters; /* * This CPU's index is assumed to already be in cache */ - cpu_counters = cm->counters[cpu_index]; + cpu_counters = cm->counters[thread_index]; CLIB_PREFETCH (cpu_counters + index, CLIB_CACHE_LINE_BYTES, STORE); } diff --git a/src/vlib/error.c b/src/vlib/error.c index a2c23176..e4ed4ee3 100644 --- a/src/vlib/error.c +++ b/src/vlib/error.c @@ -149,7 +149,7 @@ vlib_register_errors (vlib_main_t * vm, vlib_node_t *n = vlib_get_node (vm, node_index); uword l; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); /* Free up any previous error strings. */ if (n->n_errors > 0) diff --git a/src/vlib/global_funcs.h b/src/vlib/global_funcs.h index f51ec381..9dd01fbf 100644 --- a/src/vlib/global_funcs.h +++ b/src/vlib/global_funcs.h @@ -23,7 +23,7 @@ always_inline vlib_main_t * vlib_get_main (void) { vlib_main_t *vm; - vm = vlib_mains[os_get_cpu_number ()]; + vm = vlib_mains[vlib_get_thread_index ()]; ASSERT (vm); return vm; } diff --git a/src/vlib/main.c b/src/vlib/main.c index b22203f0..422d3e26 100644 --- a/src/vlib/main.c +++ b/src/vlib/main.c @@ -136,18 +136,18 @@ vlib_frame_alloc_to_node (vlib_main_t * vm, u32 to_node_index, else { f = clib_mem_alloc_aligned_no_fail (n, VLIB_FRAME_ALIGN); - f->cpu_index = vm->cpu_index; + f->thread_index = vm->thread_index; fi = vlib_frame_index_no_check (vm, f); } /* Poison frame when debugging. */ if (CLIB_DEBUG > 0) { - u32 save_cpu_index = f->cpu_index; + u32 save_thread_index = f->thread_index; memset (f, 0xfe, n); - f->cpu_index = save_cpu_index; + f->thread_index = save_thread_index; } /* Insert magic number. */ @@ -517,7 +517,7 @@ vlib_put_next_frame (vlib_main_t * vm, * a dangling frame reference. Each thread has its own copy of * the next_frames vector. */ - if (0 && r->cpu_index != next_runtime->cpu_index) + if (0 && r->thread_index != next_runtime->thread_index) { nf->frame_index = ~0; nf->flags &= ~(VLIB_FRAME_PENDING | VLIB_FRAME_IS_ALLOCATED); @@ -866,7 +866,7 @@ vlib_elog_main_loop_event (vlib_main_t * vm, : evm->node_call_elog_event_types, node_index), /* track */ - (vm->cpu_index ? &vlib_worker_threads[vm->cpu_index]. + (vm->thread_index ? &vlib_worker_threads[vm->thread_index]. elog_track : &em->default_track), /* data to log */ n_vectors); } @@ -963,7 +963,7 @@ dispatch_node (vlib_main_t * vm, vm->cpu_time_last_node_dispatch = last_time_stamp; - if (1 /* || vm->cpu_index == node->cpu_index */ ) + if (1 /* || vm->thread_index == node->thread_index */ ) { vlib_main_t *stat_vm; @@ -1029,7 +1029,7 @@ dispatch_node (vlib_main_t * vm, { u32 node_name, vector_length, is_polling; } *ed; - vlib_worker_thread_t *w = vlib_worker_threads + vm->cpu_index; + vlib_worker_thread_t *w = vlib_worker_threads + vm->thread_index; #endif if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT diff --git a/src/vlib/main.h b/src/vlib/main.h index 0197b4f3..329bf073 100644 --- a/src/vlib/main.h +++ b/src/vlib/main.h @@ -156,7 +156,7 @@ typedef struct vlib_main_t uword *init_functions_called; /* to compare with node runtime */ - u32 cpu_index; + u32 thread_index; void **mbuf_alloc_list; diff --git a/src/vlib/node.c b/src/vlib/node.c index dc0a4de5..bbd3a42e 100644 --- a/src/vlib/node.c +++ b/src/vlib/node.c @@ -99,7 +99,7 @@ vlib_node_runtime_update (vlib_main_t * vm, u32 node_index, u32 next_index) vlib_pending_frame_t *pf; i32 i, j, n_insert; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); vlib_worker_thread_barrier_sync (vm); diff --git a/src/vlib/node.h b/src/vlib/node.h index fc7e7da2..1e2f4c38 100644 --- a/src/vlib/node.h +++ b/src/vlib/node.h @@ -344,8 +344,8 @@ typedef struct vlib_frame_t /* Number of vector elements currently in frame. */ u16 n_vectors; - /* Owner cpuid / heap id */ - u16 cpu_index; + /* Owner thread / heap id */ + u16 thread_index; /* Scalar and vector arguments to next node. */ u8 arguments[0]; @@ -459,7 +459,7 @@ typedef struct vlib_node_runtime_t zero before first run of this node. */ - u16 cpu_index; /**< CPU this node runs on */ + u16 thread_index; /**< thread this node runs on */ u8 runtime_data[0]; /**< Function dependent node-runtime data. This data is diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h index 1f7d94e1..54e36874 100644 --- a/src/vlib/node_funcs.h +++ b/src/vlib/node_funcs.h @@ -201,9 +201,9 @@ always_inline vlib_frame_t * vlib_get_frame_no_check (vlib_main_t * vm, uword frame_index) { vlib_frame_t *f; - u32 cpu_index = frame_index & VLIB_CPU_MASK; + u32 thread_index = frame_index & VLIB_CPU_MASK; u32 offset = frame_index & VLIB_OFFSET_MASK; - vm = vlib_mains[cpu_index]; + vm = vlib_mains[thread_index]; f = vm->heap_base + offset; return f; } @@ -215,10 +215,10 @@ vlib_frame_index_no_check (vlib_main_t * vm, vlib_frame_t * f) ASSERT (((uword) f & VLIB_CPU_MASK) == 0); - vm = vlib_mains[f->cpu_index]; + vm = vlib_mains[f->thread_index]; i = ((u8 *) f - (u8 *) vm->heap_base); - return i | f->cpu_index; + return i | f->thread_index; } always_inline vlib_frame_t * diff --git a/src/vlib/threads.c b/src/vlib/threads.c index ef3a24d3..4a111f8d 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -35,27 +35,12 @@ vl (void *p) vlib_worker_thread_t *vlib_worker_threads; vlib_thread_main_t vlib_thread_main; +__thread uword vlib_thread_index = 0; + uword os_get_cpu_number (void) { - void *sp; - uword n; - u32 len; - - len = vec_len (vlib_thread_stacks); - if (len == 0) - return 0; - - /* Get any old stack address. */ - sp = &sp; - - n = ((uword) sp - (uword) vlib_thread_stacks[0]) - >> VLIB_LOG2_THREAD_STACK_SIZE; - - /* "processes" have their own stacks, and they always run in thread 0 */ - n = n >= len ? 0 : n; - - return n; + return vlib_thread_index; } uword @@ -275,21 +260,6 @@ vlib_thread_init (vlib_main_t * vm) return 0; } -vlib_worker_thread_t * -vlib_alloc_thread (vlib_main_t * vm) -{ - vlib_worker_thread_t *w; - - if (vec_len (vlib_worker_threads) >= vec_len (vlib_thread_stacks)) - { - clib_warning ("out of worker threads... Quitting..."); - exit (1); - } - vec_add2 (vlib_worker_threads, w, 1); - w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads]; - return w; -} - vlib_frame_queue_t * vlib_frame_queue_alloc (int nelts) { @@ -427,7 +397,7 @@ vlib_frame_queue_enqueue (vlib_main_t * vm, u32 node_runtime_index, f64 b4 = vlib_time_now_ticks (vm, before); vlib_worker_thread_barrier_check (vm, b4); /* Bad idea. Dequeue -> enqueue -> dequeue -> trouble */ - // vlib_frame_queue_dequeue (vm->cpu_index, vm, nm); + // vlib_frame_queue_dequeue (vm->thread_index, vm, nm); } elt = fq->elts + (new_tail & (fq->nelts - 1)); @@ -497,6 +467,8 @@ vlib_worker_thread_bootstrap_fn (void *arg) w->lwp = syscall (SYS_gettid); w->thread_id = pthread_self (); + vlib_thread_index = w - vlib_worker_threads; + rv = (void *) clib_calljmp ((uword (*)(uword)) w->thread_function, (uword) arg, w->thread_stack + VLIB_THREAD_STACK_SIZE); @@ -610,7 +582,9 @@ start_workers (vlib_main_t * vm) mheap_alloc (0 /* use VM */ , tr->mheap_size); else w->thread_mheap = main_heap; - w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads]; + + w->thread_stack = + vlib_thread_stack_init (w - vlib_worker_threads); w->thread_function = tr->function; w->thread_function_arg = w; w->instance_id = k; @@ -630,7 +604,7 @@ start_workers (vlib_main_t * vm) vm_clone = clib_mem_alloc (sizeof (*vm_clone)); clib_memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone)); - vm_clone->cpu_index = worker_thread_index; + vm_clone->thread_index = worker_thread_index; vm_clone->heap_base = w->thread_mheap; vm_clone->mbuf_alloc_list = 0; vm_clone->init_functions_called = @@ -679,7 +653,7 @@ start_workers (vlib_main_t * vm) vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) { vlib_node_t *n = vlib_get_node (vm, rt->node_index); - rt->cpu_index = vm_clone->cpu_index; + rt->thread_index = vm_clone->thread_index; /* copy initial runtime_data from node */ if (n->runtime_data && n->runtime_data_bytes > 0) clib_memcpy (rt->runtime_data, n->runtime_data, @@ -692,7 +666,7 @@ start_workers (vlib_main_t * vm) vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) { vlib_node_t *n = vlib_get_node (vm, rt->node_index); - rt->cpu_index = vm_clone->cpu_index; + rt->thread_index = vm_clone->thread_index; /* copy initial runtime_data from node */ if (n->runtime_data && n->runtime_data_bytes > 0) clib_memcpy (rt->runtime_data, n->runtime_data, @@ -756,7 +730,8 @@ start_workers (vlib_main_t * vm) mheap_alloc (0 /* use VM */ , tr->mheap_size); else w->thread_mheap = main_heap; - w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads]; + w->thread_stack = + vlib_thread_stack_init (w - vlib_worker_threads); w->thread_function = tr->function; w->thread_function_arg = w; w->instance_id = j; @@ -827,7 +802,7 @@ vlib_worker_thread_node_runtime_update (void) uword n_calls, uword n_vectors, uword n_clocks); - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); if (vec_len (vlib_mains) == 1) return; @@ -835,7 +810,7 @@ vlib_worker_thread_node_runtime_update (void) vm = vlib_mains[0]; nm = &vm->node_main; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); ASSERT (*vlib_worker_threads->wait_at_barrier == 1); /* @@ -955,7 +930,7 @@ vlib_worker_thread_node_runtime_update (void) vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]) { vlib_node_t *n = vlib_get_node (vm, rt->node_index); - rt->cpu_index = vm_clone->cpu_index; + rt->thread_index = vm_clone->thread_index; /* copy runtime_data, will be overwritten later for existing rt */ if (n->runtime_data && n->runtime_data_bytes > 0) clib_memcpy (rt->runtime_data, n->runtime_data, @@ -981,7 +956,7 @@ vlib_worker_thread_node_runtime_update (void) vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]) { vlib_node_t *n = vlib_get_node (vm, rt->node_index); - rt->cpu_index = vm_clone->cpu_index; + rt->thread_index = vm_clone->thread_index; /* copy runtime_data, will be overwritten later for existing rt */ if (n->runtime_data && n->runtime_data_bytes > 0) clib_memcpy (rt->runtime_data, n->runtime_data, @@ -1180,7 +1155,7 @@ vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which) if (vlib_mains == 0) return; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); vlib_worker_thread_barrier_sync (vm); switch (which) @@ -1212,7 +1187,7 @@ vlib_worker_thread_barrier_sync (vlib_main_t * vm) vlib_worker_threads[0].barrier_sync_count++; - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); deadline = vlib_time_now (vm) + BARRIER_SYNC_TIMEOUT; @@ -1260,7 +1235,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm) int vlib_frame_queue_dequeue (vlib_main_t * vm, vlib_frame_queue_main_t * fqm) { - u32 thread_id = vm->cpu_index; + u32 thread_id = vm->thread_index; vlib_frame_queue_t *fq = fqm->vlib_frame_queues[thread_id]; vlib_frame_queue_elt_t *elt; u32 *from, *to; @@ -1393,7 +1368,7 @@ vlib_worker_thread_fn (void *arg) vlib_main_t *vm = vlib_get_main (); clib_error_t *e; - ASSERT (vm->cpu_index == os_get_cpu_number ()); + ASSERT (vm->thread_index == vlib_get_thread_index ()); vlib_worker_thread_init (w); clib_time_init (&vm->clib_time); diff --git a/src/vlib/threads.h b/src/vlib/threads.h index eca4fc26..101d3d4a 100644 --- a/src/vlib/threads.h +++ b/src/vlib/threads.h @@ -153,8 +153,6 @@ typedef struct /* Called early, in thread 0's context */ clib_error_t *vlib_thread_init (vlib_main_t * vm); -vlib_worker_thread_t *vlib_alloc_thread (vlib_main_t * vm); - int vlib_frame_queue_enqueue (vlib_main_t * vm, u32 node_runtime_index, u32 frame_queue_index, vlib_frame_t * frame, vlib_frame_queue_msg_type_t type); @@ -183,12 +181,19 @@ u32 vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts); void vlib_worker_thread_barrier_sync (vlib_main_t * vm); void vlib_worker_thread_barrier_release (vlib_main_t * vm); +extern __thread uword vlib_thread_index; +static_always_inline uword +vlib_get_thread_index (void) +{ + return vlib_thread_index; +} + always_inline void vlib_smp_unsafe_warning (void) { if (CLIB_DEBUG > 0) { - if (os_get_cpu_number ()) + if (vlib_get_thread_index ()) fformat (stderr, "%s: SMP unsafe warning...\n", __FUNCTION__); } } @@ -331,21 +336,21 @@ vlib_num_workers () } always_inline u32 -vlib_get_worker_cpu_index (u32 worker_index) +vlib_get_worker_thread_index (u32 worker_index) { return worker_index + 1; } always_inline u32 -vlib_get_worker_index (u32 cpu_index) +vlib_get_worker_index (u32 thread_index) { - return cpu_index - 1; + return thread_index - 1; } always_inline u32 vlib_get_current_worker_index () { - return os_get_cpu_number () - 1; + return vlib_get_thread_index () - 1; } static inline void @@ -467,6 +472,8 @@ vlib_get_worker_handoff_queue_elt (u32 frame_queue_index, return elt; } +u8 *vlib_thread_stack_init (uword thread_index); + int vlib_thread_cb_register (struct vlib_main_t *vm, vlib_thread_callbacks_t * cb); diff --git a/src/vlib/unix/cj.c b/src/vlib/unix/cj.c index 33ba163a..7c1e9475 100644 --- a/src/vlib/unix/cj.c +++ b/src/vlib/unix/cj.c @@ -48,7 +48,7 @@ cj_log (u32 type, void *data0, void *data1) r = (cj_record_t *) & (cjm->records[new_tail & (cjm->num_records - 1)]); r->time = vlib_time_now (cjm->vlib_main); - r->cpu = os_get_cpu_number (); + r->thread_index = vlib_get_thread_index (); r->type = type; r->data[0] = pointer_to_uword (data0); r->data[1] = pointer_to_uword (data1); @@ -133,7 +133,8 @@ static inline void cj_dump_one_record (cj_record_t * r) { fprintf (stderr, "[%d]: %10.6f T%02d %llx %llx\n", - r->cpu, r->time, r->type, (long long unsigned int) r->data[0], + r->thread_index, r->time, r->type, + (long long unsigned int) r->data[0], (long long unsigned int) r->data[1]); } @@ -161,7 +162,7 @@ cj_dump_internal (u8 filter0_enable, u64 filter0, index = (cjm->tail + 1) & (cjm->num_records - 1); r = &(cjm->records[index]); - if (r->cpu != (u32) ~ 0) + if (r->thread_index != (u32) ~ 0) { /* Yes, dump from tail + 1 to the end */ for (i = index; i < cjm->num_records; i++) diff --git a/src/vlib/unix/cj.h b/src/vlib/unix/cj.h index 67626afe..d0a1d46e 100644 --- a/src/vlib/unix/cj.h +++ b/src/vlib/unix/cj.h @@ -23,7 +23,7 @@ typedef struct { f64 time; - u32 cpu; + u32 thread_index; u32 type; u64 data[2]; } cj_record_t; diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c index 6b96cc0d..db5ddd64 100644 --- a/src/vlib/unix/main.c +++ b/src/vlib/unix/main.c @@ -510,13 +510,28 @@ thread0 (uword arg) return i; } +u8 * +vlib_thread_stack_init (uword thread_index) +{ + vec_validate (vlib_thread_stacks, thread_index); + vlib_thread_stacks[thread_index] = clib_mem_alloc_aligned + (VLIB_THREAD_STACK_SIZE, VLIB_THREAD_STACK_SIZE); + + /* + * Disallow writes to the bottom page of the stack, to + * catch stack overflows. + */ + if (mprotect (vlib_thread_stacks[thread_index], + clib_mem_get_page_size (), PROT_READ) < 0) + clib_unix_warning ("thread stack"); + return vlib_thread_stacks[thread_index]; +} + int vlib_unix_main (int argc, char *argv[]) { vlib_main_t *vm = &vlib_global_main; /* one and only time for this! */ - vlib_thread_main_t *tm = &vlib_thread_main; unformat_input_t input; - u8 *thread_stacks; clib_error_t *e; int i; @@ -548,29 +563,9 @@ vlib_unix_main (int argc, char *argv[]) } unformat_free (&input); - /* - * allocate n x VLIB_THREAD_STACK_SIZE stacks, aligned to a - * VLIB_THREAD_STACK_SIZE boundary - * See also: os_get_cpu_number() in vlib/vlib/threads.c - */ - thread_stacks = clib_mem_alloc_aligned - ((uword) tm->n_thread_stacks * VLIB_THREAD_STACK_SIZE, - VLIB_THREAD_STACK_SIZE); - - vec_validate (vlib_thread_stacks, tm->n_thread_stacks - 1); - for (i = 0; i < vec_len (vlib_thread_stacks); i++) - { - vlib_thread_stacks[i] = thread_stacks; - - /* - * Disallow writes to the bottom page of the stack, to - * catch stack overflows. - */ - if (mprotect (thread_stacks, clib_mem_get_page_size (), PROT_READ) < 0) - clib_unix_warning ("thread stack"); + vlib_thread_stack_init (0); - thread_stacks += VLIB_THREAD_STACK_SIZE; - } + vlib_thread_index = 0; i = clib_calljmp (thread0, (uword) vm, (void *) (vlib_thread_stacks[0] + diff --git a/src/vnet/adj/adj_l2.c b/src/vnet/adj/adj_l2.c index f68e54e0..20d70dd4 100644 --- a/src/vnet/adj/adj_l2.c +++ b/src/vnet/adj/adj_l2.c @@ -52,7 +52,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, { u32 * from = vlib_frame_vector_args (frame); u32 n_left_from, n_left_to_next, * to_next, next_index; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); ethernet_main_t * em = ðernet_main; n_left_from = frame->n_vectors; @@ -93,7 +93,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index; vlib_increment_combined_counter(&adjacency_counters, - cpu_index, + thread_index, adj_index0, /* packet increment */ 0, /* byte increment */ rw_len0); diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c index e8087f08..5756de43 100644 --- a/src/vnet/adj/adj_midchain.c +++ b/src/vnet/adj/adj_midchain.c @@ -49,7 +49,7 @@ adj_midchain_tx_inline (vlib_main_t * vm, u32 next_index; vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; /* Vector of buffer / pkt indices we're supposed to process */ from = vlib_frame_vector_args (frame); @@ -124,13 +124,13 @@ adj_midchain_tx_inline (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, + thread_index, adj0->rewrite_header.sw_if_index, 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, + thread_index, adj1->rewrite_header.sw_if_index, 1, vlib_buffer_length_in_chain (vm, b1)); @@ -181,7 +181,7 @@ adj_midchain_tx_inline (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, + thread_index, adj0->rewrite_header.sw_if_index, 1, vlib_buffer_length_in_chain (vm, b0)); diff --git a/src/vnet/adj/adj_nsh.c b/src/vnet/adj/adj_nsh.c index 9a0f9d8b..128570b0 100644 --- a/src/vnet/adj/adj_nsh.c +++ b/src/vnet/adj/adj_nsh.c @@ -53,7 +53,7 @@ adj_nsh_rewrite_inline (vlib_main_t * vm, { u32 * from = vlib_frame_vector_args (frame); u32 n_left_from, n_left_to_next, * to_next, next_index; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -94,7 +94,7 @@ adj_nsh_rewrite_inline (vlib_main_t * vm, vnet_buffer(p0)->ip.save_rewrite_length = rw_len0; vlib_increment_combined_counter(&adjacency_counters, - cpu_index, + thread_index, adj_index0, /* packet increment */ 0, /* byte increment */ rw_len0); diff --git a/src/vnet/classify/vnet_classify.c b/src/vnet/classify/vnet_classify.c index 98842a48..70a189b0 100644 --- a/src/vnet/classify/vnet_classify.c +++ b/src/vnet/classify/vnet_classify.c @@ -251,12 +251,12 @@ static inline void make_working_copy vnet_classify_entry_##size##_t * working_copy##size = 0; foreach_size_in_u32x4; #undef _ - u32 cpu_number = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); - if (cpu_number >= vec_len (t->working_copies)) + if (thread_index >= vec_len (t->working_copies)) { oldheap = clib_mem_set_heap (t->mheap); - vec_validate (t->working_copies, cpu_number); + vec_validate (t->working_copies, thread_index); clib_mem_set_heap (oldheap); } @@ -265,7 +265,7 @@ static inline void make_working_copy * updates from multiple threads will not result in sporadic, spurious * lookup failures. */ - working_copy = t->working_copies[cpu_number]; + working_copy = t->working_copies[thread_index]; t->saved_bucket.as_u64 = b->as_u64; oldheap = clib_mem_set_heap (t->mheap); @@ -290,7 +290,7 @@ static inline void make_working_copy default: abort(); } - t->working_copies[cpu_number] = working_copy; + t->working_copies[thread_index] = working_copy; } _vec_len(working_copy) = (1<log2_pages)*t->entries_per_page; @@ -318,7 +318,7 @@ static inline void make_working_copy working_bucket.offset = vnet_classify_get_offset (t, working_copy); CLIB_MEMORY_BARRIER(); b->as_u64 = working_bucket.as_u64; - t->working_copies[cpu_number] = working_copy; + t->working_copies[thread_index] = working_copy; } static vnet_classify_entry_t * @@ -387,7 +387,7 @@ int vnet_classify_add_del (vnet_classify_table_t * t, int i; u64 hash, new_hash; u32 new_log2_pages; - u32 cpu_number = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u8 * key_minus_skip; ASSERT ((add_v->flags & VNET_CLASSIFY_ENTRY_FREE) == 0); @@ -498,7 +498,7 @@ int vnet_classify_add_del (vnet_classify_table_t * t, new_log2_pages = t->saved_bucket.log2_pages + 1; expand_again: - working_copy = t->working_copies[cpu_number]; + working_copy = t->working_copies[thread_index]; new_v = split_and_rehash (t, working_copy, new_log2_pages); if (new_v == 0) diff --git a/src/vnet/cop/ip4_whitelist.c b/src/vnet/cop/ip4_whitelist.c index 6ef3d7d7..1b5e336b 100644 --- a/src/vnet/cop/ip4_whitelist.c +++ b/src/vnet/cop/ip4_whitelist.c @@ -60,7 +60,7 @@ ip4_cop_whitelist_node_fn (vlib_main_t * vm, cop_feature_type_t next_index; cop_main_t *cm = &cop_main; vlib_combined_counter_main_t * vcm = &load_balance_main.lbm_via_counters; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -177,12 +177,12 @@ ip4_cop_whitelist_node_fn (vlib_main_t * vm, dpo1 = load_balance_get_bucket_i(lb1, 0); vlib_increment_combined_counter - (vcm, cpu_index, lb_index0, 1, + (vcm, thread_index, lb_index0, 1, vlib_buffer_length_in_chain (vm, b0) + sizeof(ethernet_header_t)); vlib_increment_combined_counter - (vcm, cpu_index, lb_index1, 1, + (vcm, thread_index, lb_index1, 1, vlib_buffer_length_in_chain (vm, b1) + sizeof(ethernet_header_t)); @@ -273,7 +273,7 @@ ip4_cop_whitelist_node_fn (vlib_main_t * vm, dpo0 = load_balance_get_bucket_i(lb0, 0); vlib_increment_combined_counter - (vcm, cpu_index, lb_index0, 1, + (vcm, thread_index, lb_index0, 1, vlib_buffer_length_in_chain (vm, b0) + sizeof(ethernet_header_t)); diff --git a/src/vnet/cop/ip6_whitelist.c b/src/vnet/cop/ip6_whitelist.c index c2e16ccf..f3fe62e3 100644 --- a/src/vnet/cop/ip6_whitelist.c +++ b/src/vnet/cop/ip6_whitelist.c @@ -61,7 +61,7 @@ ip6_cop_whitelist_node_fn (vlib_main_t * vm, cop_main_t *cm = &cop_main; ip6_main_t * im6 = &ip6_main; vlib_combined_counter_main_t * vcm = &load_balance_main.lbm_via_counters; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -153,12 +153,12 @@ ip6_cop_whitelist_node_fn (vlib_main_t * vm, dpo1 = load_balance_get_bucket_i(lb1, 0); vlib_increment_combined_counter - (vcm, cpu_index, lb_index0, 1, + (vcm, thread_index, lb_index0, 1, vlib_buffer_length_in_chain (vm, b0) + sizeof(ethernet_header_t)); vlib_increment_combined_counter - (vcm, cpu_index, lb_index1, 1, + (vcm, thread_index, lb_index1, 1, vlib_buffer_length_in_chain (vm, b1) + sizeof(ethernet_header_t)); @@ -233,7 +233,7 @@ ip6_cop_whitelist_node_fn (vlib_main_t * vm, dpo0 = load_balance_get_bucket_i(lb0, 0); vlib_increment_combined_counter - (vcm, cpu_index, lb_index0, 1, + (vcm, thread_index, lb_index0, 1, vlib_buffer_length_in_chain (vm, b0) + sizeof(ethernet_header_t)); diff --git a/src/vnet/devices/af_packet/node.c b/src/vnet/devices/af_packet/node.c index ba337f3f..76980102 100644 --- a/src/vnet/devices/af_packet/node.c +++ b/src/vnet/devices/af_packet/node.c @@ -124,7 +124,7 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 frame_num = apif->rx_req->tp_frame_nr; u8 *block_start = apif->rx_ring + block * block_size; uword n_trace = vlib_get_trace_count (vm, node); - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 n_buffer_bytes = vlib_buffer_free_list_buffer_size (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); u32 min_bufs = apif->rx_req->tp_frame_size / n_buffer_bytes; @@ -132,15 +132,15 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, if (apif->per_interface_next_index != ~0) next_index = apif->per_interface_next_index; - n_free_bufs = vec_len (apm->rx_buffers[cpu_index]); + n_free_bufs = vec_len (apm->rx_buffers[thread_index]); if (PREDICT_FALSE (n_free_bufs < VLIB_FRAME_SIZE)) { - vec_validate (apm->rx_buffers[cpu_index], + vec_validate (apm->rx_buffers[thread_index], VLIB_FRAME_SIZE + n_free_bufs - 1); n_free_bufs += - vlib_buffer_alloc (vm, &apm->rx_buffers[cpu_index][n_free_bufs], + vlib_buffer_alloc (vm, &apm->rx_buffers[thread_index][n_free_bufs], VLIB_FRAME_SIZE); - _vec_len (apm->rx_buffers[cpu_index]) = n_free_bufs; + _vec_len (apm->rx_buffers[thread_index]) = n_free_bufs; } rx_frame = apif->next_rx_frame; @@ -163,11 +163,11 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, { /* grab free buffer */ u32 last_empty_buffer = - vec_len (apm->rx_buffers[cpu_index]) - 1; + vec_len (apm->rx_buffers[thread_index]) - 1; prev_bi0 = bi0; - bi0 = apm->rx_buffers[cpu_index][last_empty_buffer]; + bi0 = apm->rx_buffers[thread_index][last_empty_buffer]; b0 = vlib_get_buffer (vm, bi0); - _vec_len (apm->rx_buffers[cpu_index]) = last_empty_buffer; + _vec_len (apm->rx_buffers[thread_index]) = last_empty_buffer; n_free_bufs--; /* copy data */ @@ -236,9 +236,9 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (vnet_get_main ()->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number (), apif->hw_if_index, n_rx_packets, n_rx_bytes); + vlib_get_thread_index (), apif->hw_if_index, n_rx_packets, n_rx_bytes); - vnet_device_increment_rx_packets (cpu_index, n_rx_packets); + vnet_device_increment_rx_packets (thread_index, n_rx_packets); return n_rx_packets; } diff --git a/src/vnet/devices/devices.c b/src/vnet/devices/devices.c index 41645220..5e5e812c 100644 --- a/src/vnet/devices/devices.c +++ b/src/vnet/devices/devices.c @@ -104,7 +104,7 @@ vnet_device_queue_sort (void *a1, void *a2) void vnet_device_input_assign_thread (u32 hw_if_index, - u16 queue_id, uword cpu_index) + u16 queue_id, uword thread_index) { vnet_main_t *vnm = vnet_get_main (); vnet_device_main_t *vdm = &vnet_device_main; @@ -115,19 +115,19 @@ vnet_device_input_assign_thread (u32 hw_if_index, ASSERT (hw->input_node_index > 0); - if (vdm->first_worker_cpu_index == 0) - cpu_index = 0; + if (vdm->first_worker_thread_index == 0) + thread_index = 0; - if (cpu_index != 0 && - (cpu_index < vdm->first_worker_cpu_index || - cpu_index > vdm->last_worker_cpu_index)) + if (thread_index != 0 && + (thread_index < vdm->first_worker_thread_index || + thread_index > vdm->last_worker_thread_index)) { - cpu_index = vdm->next_worker_cpu_index++; - if (vdm->next_worker_cpu_index > vdm->last_worker_cpu_index) - vdm->next_worker_cpu_index = vdm->first_worker_cpu_index; + thread_index = vdm->next_worker_thread_index++; + if (vdm->next_worker_thread_index > vdm->last_worker_thread_index) + vdm->next_worker_thread_index = vdm->first_worker_thread_index; } - vm = vlib_mains[cpu_index]; + vm = vlib_mains[thread_index]; rt = vlib_node_get_runtime_data (vm, hw->input_node_index); vec_add2 (rt->devices_and_queues, dq, 1); @@ -136,33 +136,33 @@ vnet_device_input_assign_thread (u32 hw_if_index, dq->queue_id = queue_id; vec_sort_with_function (rt->devices_and_queues, vnet_device_queue_sort); - vec_validate (hw->input_node_cpu_index_by_queue, queue_id); - hw->input_node_cpu_index_by_queue[queue_id] = cpu_index; + vec_validate (hw->input_node_thread_index_by_queue, queue_id); + hw->input_node_thread_index_by_queue[queue_id] = thread_index; } static int vnet_device_input_unassign_thread (u32 hw_if_index, u16 queue_id, - uword cpu_index) + uword thread_index) { vnet_main_t *vnm = vnet_get_main (); vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); vnet_device_input_runtime_t *rt; vnet_device_and_queue_t *dq; - uword old_cpu_index; + uword old_thread_index; - if (hw->input_node_cpu_index_by_queue == 0) + if (hw->input_node_thread_index_by_queue == 0) return VNET_API_ERROR_INVALID_INTERFACE; - if (vec_len (hw->input_node_cpu_index_by_queue) < queue_id + 1) + if (vec_len (hw->input_node_thread_index_by_queue) < queue_id + 1) return VNET_API_ERROR_INVALID_INTERFACE; - old_cpu_index = hw->input_node_cpu_index_by_queue[queue_id]; + old_thread_index = hw->input_node_thread_index_by_queue[queue_id]; - if (old_cpu_index == cpu_index) + if (old_thread_index == thread_index) return 0; rt = - vlib_node_get_runtime_data (vlib_mains[old_cpu_index], + vlib_node_get_runtime_data (vlib_mains[old_thread_index], hw->input_node_index); vec_foreach (dq, rt->devices_and_queues) @@ -240,7 +240,7 @@ set_device_placement (vlib_main_t * vm, unformat_input_t * input, vnet_device_main_t *vdm = &vnet_device_main; u32 hw_if_index = (u32) ~ 0; u32 queue_id = (u32) 0; - u32 cpu_index = (u32) ~ 0; + u32 thread_index = (u32) ~ 0; int rv; if (!unformat_user (input, unformat_line_input, line_input)) @@ -253,10 +253,10 @@ set_device_placement (vlib_main_t * vm, unformat_input_t * input, ; else if (unformat (line_input, "queue %d", &queue_id)) ; - else if (unformat (line_input, "main", &cpu_index)) - cpu_index = 0; - else if (unformat (line_input, "worker %d", &cpu_index)) - cpu_index += vdm->first_worker_cpu_index; + else if (unformat (line_input, "main", &thread_index)) + thread_index = 0; + else if (unformat (line_input, "worker %d", &thread_index)) + thread_index += vdm->first_worker_thread_index; else { error = clib_error_return (0, "parse error: '%U'", @@ -271,16 +271,17 @@ set_device_placement (vlib_main_t * vm, unformat_input_t * input, if (hw_if_index == (u32) ~ 0) return clib_error_return (0, "please specify valid interface name"); - if (cpu_index > vdm->last_worker_cpu_index) + if (thread_index > vdm->last_worker_thread_index) return clib_error_return (0, "please specify valid worker thread or main"); - rv = vnet_device_input_unassign_thread (hw_if_index, queue_id, cpu_index); + rv = + vnet_device_input_unassign_thread (hw_if_index, queue_id, thread_index); if (rv) return clib_error_return (0, "not found"); - vnet_device_input_assign_thread (hw_if_index, queue_id, cpu_index); + vnet_device_input_assign_thread (hw_if_index, queue_id, thread_index); return 0; } @@ -326,9 +327,9 @@ vnet_device_init (vlib_main_t * vm) tr = p ? (vlib_thread_registration_t *) p[0] : 0; if (tr && tr->count > 0) { - vdm->first_worker_cpu_index = tr->first_index; - vdm->next_worker_cpu_index = tr->first_index; - vdm->last_worker_cpu_index = tr->first_index + tr->count - 1; + vdm->first_worker_thread_index = tr->first_index; + vdm->next_worker_thread_index = tr->first_index; + vdm->last_worker_thread_index = tr->first_index + tr->count - 1; } return 0; } diff --git a/src/vnet/devices/devices.h b/src/vnet/devices/devices.h index bbb29fe3..966f8302 100644 --- a/src/vnet/devices/devices.h +++ b/src/vnet/devices/devices.h @@ -50,9 +50,9 @@ typedef struct typedef struct { vnet_device_per_worker_data_t *workers; - uword first_worker_cpu_index; - uword last_worker_cpu_index; - uword next_worker_cpu_index; + uword first_worker_thread_index; + uword last_worker_thread_index; + uword next_worker_thread_index; } vnet_device_main_t; typedef struct @@ -80,7 +80,7 @@ vnet_set_device_input_node (u32 hw_if_index, u32 node_index) } void vnet_device_input_assign_thread (u32 hw_if_index, u16 queue_id, - uword cpu_index); + uword thread_index); static inline u64 vnet_get_aggregate_rx_packets (void) @@ -95,12 +95,12 @@ vnet_get_aggregate_rx_packets (void) } static inline void -vnet_device_increment_rx_packets (u32 cpu_index, u64 count) +vnet_device_increment_rx_packets (u32 thread_index, u64 count) { vnet_device_main_t *vdm = &vnet_device_main; vnet_device_per_worker_data_t *pwd; - pwd = vec_elt_at_index (vdm->workers, cpu_index); + pwd = vec_elt_at_index (vdm->workers, thread_index); pwd->aggregate_rx_packets += count; } @@ -117,9 +117,9 @@ vnet_device_input_set_interrupt_pending (vnet_main_t * vnm, u32 hw_if_index, { vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); - ASSERT (queue_id < vec_len (hw->input_node_cpu_index_by_queue)); - u32 cpu_index = hw->input_node_cpu_index_by_queue[queue_id]; - vlib_node_set_interrupt_pending (vlib_mains[cpu_index], + ASSERT (queue_id < vec_len (hw->input_node_thread_index_by_queue)); + u32 thread_index = hw->input_node_thread_index_by_queue[queue_id]; + vlib_node_set_interrupt_pending (vlib_mains[thread_index], hw->input_node_index); } diff --git a/src/vnet/devices/netmap/node.c b/src/vnet/devices/netmap/node.c index 68ea7832..e120eeae 100644 --- a/src/vnet/devices/netmap/node.c +++ b/src/vnet/devices/netmap/node.c @@ -98,22 +98,22 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 n_free_bufs; struct netmap_ring *ring; int cur_ring; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 n_buffer_bytes = vlib_buffer_free_list_buffer_size (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); if (nif->per_interface_next_index != ~0) next_index = nif->per_interface_next_index; - n_free_bufs = vec_len (nm->rx_buffers[cpu_index]); + n_free_bufs = vec_len (nm->rx_buffers[thread_index]); if (PREDICT_FALSE (n_free_bufs < VLIB_FRAME_SIZE)) { - vec_validate (nm->rx_buffers[cpu_index], + vec_validate (nm->rx_buffers[thread_index], VLIB_FRAME_SIZE + n_free_bufs - 1); n_free_bufs += - vlib_buffer_alloc (vm, &nm->rx_buffers[cpu_index][n_free_bufs], + vlib_buffer_alloc (vm, &nm->rx_buffers[thread_index][n_free_bufs], VLIB_FRAME_SIZE); - _vec_len (nm->rx_buffers[cpu_index]) = n_free_bufs; + _vec_len (nm->rx_buffers[thread_index]) = n_free_bufs; } cur_ring = nif->first_rx_ring; @@ -163,11 +163,11 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t *b0; /* grab free buffer */ u32 last_empty_buffer = - vec_len (nm->rx_buffers[cpu_index]) - 1; + vec_len (nm->rx_buffers[thread_index]) - 1; prev_bi0 = bi0; - bi0 = nm->rx_buffers[cpu_index][last_empty_buffer]; + bi0 = nm->rx_buffers[thread_index][last_empty_buffer]; b0 = vlib_get_buffer (vm, bi0); - _vec_len (nm->rx_buffers[cpu_index]) = last_empty_buffer; + _vec_len (nm->rx_buffers[thread_index]) = last_empty_buffer; n_free_bufs--; /* copy data */ @@ -247,9 +247,9 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (vnet_get_main ()->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number (), nif->hw_if_index, n_rx_packets, n_rx_bytes); + vlib_get_thread_index (), nif->hw_if_index, n_rx_packets, n_rx_bytes); - vnet_device_increment_rx_packets (cpu_index, n_rx_packets); + vnet_device_increment_rx_packets (thread_index, n_rx_packets); return n_rx_packets; } @@ -260,7 +260,7 @@ netmap_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, { int i; u32 n_rx_packets = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); netmap_main_t *nm = &netmap_main; netmap_if_t *nmi; @@ -269,7 +269,7 @@ netmap_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, nmi = vec_elt_at_index (nm->interfaces, i); if (nmi->is_admin_up && (i % nm->input_cpu_count) == - (cpu_index - nm->input_cpu_first_index)) + (thread_index - nm->input_cpu_first_index)) n_rx_packets += netmap_device_input_fn (vm, node, frame, nmi); } diff --git a/src/vnet/devices/ssvm/node.c b/src/vnet/devices/ssvm/node.c index a6c9dfd7..539b4161 100644 --- a/src/vnet/devices/ssvm/node.c +++ b/src/vnet/devices/ssvm/node.c @@ -89,7 +89,7 @@ ssvm_eth_device_input (ssvm_eth_main_t * em, ethernet_header_t *eh0; u16 type0; u32 n_rx_bytes = 0, l3_offset0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 trace_cnt __attribute__ ((unused)) = vlib_get_trace_count (vm, node); volatile u32 *lock; u32 *elt_indices; @@ -284,10 +284,10 @@ out: vlib_increment_combined_counter (vnet_get_main ()->interface_main.combined_sw_if_counters - + VNET_INTERFACE_COUNTER_RX, cpu_index, + + VNET_INTERFACE_COUNTER_RX, thread_index, intfc->vlib_hw_if_index, rx_queue_index, n_rx_bytes); - vnet_device_increment_rx_packets (cpu_index, rx_queue_index); + vnet_device_increment_rx_packets (thread_index, rx_queue_index); return rx_queue_index; } diff --git a/src/vnet/devices/virtio/vhost-user.c b/src/vnet/devices/virtio/vhost-user.c index 00807dc0..5e720f65 100644 --- a/src/vnet/devices/virtio/vhost-user.c +++ b/src/vnet/devices/virtio/vhost-user.c @@ -331,7 +331,7 @@ vhost_user_tx_thread_placement (vhost_user_intf_t * vui) { //Let's try to assign one queue to each thread u32 qid = 0; - u32 cpu_index = 0; + u32 thread_index = 0; vui->use_tx_spinlock = 0; while (1) { @@ -341,20 +341,21 @@ vhost_user_tx_thread_placement (vhost_user_intf_t * vui) if (!rxvq->started || !rxvq->enabled) continue; - vui->per_cpu_tx_qid[cpu_index] = qid; - cpu_index++; - if (cpu_index == vlib_get_thread_main ()->n_vlib_mains) + vui->per_cpu_tx_qid[thread_index] = qid; + thread_index++; + if (thread_index == vlib_get_thread_main ()->n_vlib_mains) return; } //We need to loop, meaning the spinlock has to be used vui->use_tx_spinlock = 1; - if (cpu_index == 0) + if (thread_index == 0) { //Could not find a single valid one - for (cpu_index = 0; - cpu_index < vlib_get_thread_main ()->n_vlib_mains; cpu_index++) + for (thread_index = 0; + thread_index < vlib_get_thread_main ()->n_vlib_mains; + thread_index++) { - vui->per_cpu_tx_qid[cpu_index] = 0; + vui->per_cpu_tx_qid[thread_index] = 0; } return; } @@ -368,7 +369,7 @@ vhost_user_rx_thread_placement () vhost_user_intf_t *vui; vhost_cpu_t *vhc; u32 *workers = 0; - u32 cpu_index; + u32 thread_index; vlib_main_t *vm; //Let's list all workers cpu indexes @@ -400,9 +401,9 @@ vhost_user_rx_thread_placement () continue; i %= vec_len (vui_workers); - cpu_index = vui_workers[i]; + thread_index = vui_workers[i]; i++; - vhc = &vum->cpus[cpu_index]; + vhc = &vum->cpus[thread_index]; iaq.qid = qid; iaq.vhost_iface_index = vui - vum->vhost_user_interfaces; @@ -429,14 +430,14 @@ vhost_user_rx_thread_placement () vhc->operation_mode = mode; } - for (cpu_index = vum->input_cpu_first_index; - cpu_index < vum->input_cpu_first_index + vum->input_cpu_count; - cpu_index++) + for (thread_index = vum->input_cpu_first_index; + thread_index < vum->input_cpu_first_index + vum->input_cpu_count; + thread_index++) { vlib_node_state_t state = VLIB_NODE_STATE_POLLING; - vhc = &vum->cpus[cpu_index]; - vm = vlib_mains ? vlib_mains[cpu_index] : &vlib_global_main; + vhc = &vum->cpus[thread_index]; + vm = vlib_mains ? vlib_mains[thread_index] : &vlib_global_main; switch (vhc->operation_mode) { case VHOST_USER_INTERRUPT_MODE: @@ -532,7 +533,7 @@ vhost_user_set_interrupt_pending (vhost_user_intf_t * vui, u32 ifq) { vhost_user_main_t *vum = &vhost_user_main; vhost_cpu_t *vhc; - u32 cpu_index; + u32 thread_index; vhost_iface_and_queue_t *vhiq; vlib_main_t *vm; u32 ifq2; @@ -553,8 +554,8 @@ vhost_user_set_interrupt_pending (vhost_user_intf_t * vui, u32 ifq) if ((vhiq->vhost_iface_index == (ifq >> 8)) && (VHOST_VRING_IDX_TX (vhiq->qid) == (ifq & 0xff))) { - cpu_index = vhc - vum->cpus; - vm = vlib_mains ? vlib_mains[cpu_index] : &vlib_global_main; + thread_index = vhc - vum->cpus; + vm = vlib_mains ? vlib_mains[thread_index] : &vlib_global_main; /* * Convert RX virtqueue number in the lower byte to vring * queue index for the input node process. Top bytes contain @@ -1592,7 +1593,7 @@ vhost_user_if_input (vlib_main_t * vm, u32 n_trace = vlib_get_trace_count (vm, node); u16 qsz_mask; u32 map_hint = 0; - u16 cpu_index = os_get_cpu_number (); + u16 thread_index = vlib_get_thread_index (); u16 copy_len = 0; { @@ -1651,32 +1652,32 @@ vhost_user_if_input (vlib_main_t * vm, * in the loop and come back later. This is not an issue as for big packet, * processing cost really comes from the memory copy. */ - if (PREDICT_FALSE (vum->cpus[cpu_index].rx_buffers_len < n_left + 1)) + if (PREDICT_FALSE (vum->cpus[thread_index].rx_buffers_len < n_left + 1)) { - u32 curr_len = vum->cpus[cpu_index].rx_buffers_len; - vum->cpus[cpu_index].rx_buffers_len += + u32 curr_len = vum->cpus[thread_index].rx_buffers_len; + vum->cpus[thread_index].rx_buffers_len += vlib_buffer_alloc_from_free_list (vm, - vum->cpus[cpu_index].rx_buffers + + vum->cpus[thread_index].rx_buffers + curr_len, VHOST_USER_RX_BUFFERS_N - curr_len, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); if (PREDICT_FALSE - (vum->cpus[cpu_index].rx_buffers_len < + (vum->cpus[thread_index].rx_buffers_len < VHOST_USER_RX_BUFFER_STARVATION)) { /* In case of buffer starvation, discard some packets from the queue * and log the event. * We keep doing best effort for the remaining packets. */ - u32 flush = (n_left + 1 > vum->cpus[cpu_index].rx_buffers_len) ? - n_left + 1 - vum->cpus[cpu_index].rx_buffers_len : 1; + u32 flush = (n_left + 1 > vum->cpus[thread_index].rx_buffers_len) ? + n_left + 1 - vum->cpus[thread_index].rx_buffers_len : 1; flush = vhost_user_rx_discard_packet (vm, vui, txvq, flush); n_left -= flush; vlib_increment_simple_counter (vnet_main. interface_main.sw_if_counters + VNET_INTERFACE_COUNTER_DROP, - os_get_cpu_number (), + vlib_get_thread_index (), vui->sw_if_index, flush); vlib_error_count (vm, vhost_user_input_node.index, @@ -1696,7 +1697,7 @@ vhost_user_if_input (vlib_main_t * vm, u32 desc_data_offset; vring_desc_t *desc_table = txvq->desc; - if (PREDICT_FALSE (vum->cpus[cpu_index].rx_buffers_len <= 1)) + if (PREDICT_FALSE (vum->cpus[thread_index].rx_buffers_len <= 1)) { /* Not enough rx_buffers * Note: We yeld on 1 so we don't need to do an additional @@ -1707,17 +1708,18 @@ vhost_user_if_input (vlib_main_t * vm, } desc_current = txvq->avail->ring[txvq->last_avail_idx & qsz_mask]; - vum->cpus[cpu_index].rx_buffers_len--; - bi_current = (vum->cpus[cpu_index].rx_buffers) - [vum->cpus[cpu_index].rx_buffers_len]; + vum->cpus[thread_index].rx_buffers_len--; + bi_current = (vum->cpus[thread_index].rx_buffers) + [vum->cpus[thread_index].rx_buffers_len]; b_head = b_current = vlib_get_buffer (vm, bi_current); to_next[0] = bi_current; //We do that now so we can forget about bi_current to_next++; n_left_to_next--; vlib_prefetch_buffer_with_index (vm, - (vum->cpus[cpu_index].rx_buffers) - [vum->cpus[cpu_index]. + (vum-> + cpus[thread_index].rx_buffers) + [vum->cpus[thread_index]. rx_buffers_len - 1], LOAD); /* Just preset the used descriptor id and length for later */ @@ -1791,7 +1793,7 @@ vhost_user_if_input (vlib_main_t * vm, (b_current->current_length == VLIB_BUFFER_DATA_SIZE)) { if (PREDICT_FALSE - (vum->cpus[cpu_index].rx_buffers_len == 0)) + (vum->cpus[thread_index].rx_buffers_len == 0)) { /* Cancel speculation */ to_next--; @@ -1805,17 +1807,18 @@ vhost_user_if_input (vlib_main_t * vm, * but valid. */ vhost_user_input_rewind_buffers (vm, - &vum->cpus[cpu_index], + &vum->cpus + [thread_index], b_head); n_left = 0; goto stop; } /* Get next output */ - vum->cpus[cpu_index].rx_buffers_len--; + vum->cpus[thread_index].rx_buffers_len--; u32 bi_next = - (vum->cpus[cpu_index].rx_buffers)[vum->cpus - [cpu_index].rx_buffers_len]; + (vum->cpus[thread_index].rx_buffers)[vum->cpus + [thread_index].rx_buffers_len]; b_current->next_buffer = bi_next; b_current->flags |= VLIB_BUFFER_NEXT_PRESENT; bi_current = bi_next; @@ -1823,7 +1826,7 @@ vhost_user_if_input (vlib_main_t * vm, } /* Prepare a copy order executed later for the data */ - vhost_copy_t *cpy = &vum->cpus[cpu_index].copy[copy_len]; + vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len]; copy_len++; u32 desc_data_l = desc_table[desc_current].len - desc_data_offset; @@ -1880,7 +1883,7 @@ vhost_user_if_input (vlib_main_t * vm, if (PREDICT_FALSE (copy_len >= VHOST_USER_RX_COPY_THRESHOLD)) { if (PREDICT_FALSE - (vhost_user_input_copy (vui, vum->cpus[cpu_index].copy, + (vhost_user_input_copy (vui, vum->cpus[thread_index].copy, copy_len, &map_hint))) { clib_warning @@ -1905,7 +1908,7 @@ vhost_user_if_input (vlib_main_t * vm, /* Do the memory copies */ if (PREDICT_FALSE - (vhost_user_input_copy (vui, vum->cpus[cpu_index].copy, + (vhost_user_input_copy (vui, vum->cpus[thread_index].copy, copy_len, &map_hint))) { clib_warning ("Memory mapping error on interface hw_if_index=%d " @@ -1933,9 +1936,9 @@ vhost_user_if_input (vlib_main_t * vm, vlib_increment_combined_counter (vnet_main.interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number (), vui->sw_if_index, n_rx_packets, n_rx_bytes); + vlib_get_thread_index (), vui->sw_if_index, n_rx_packets, n_rx_bytes); - vnet_device_increment_rx_packets (cpu_index, n_rx_packets); + vnet_device_increment_rx_packets (thread_index, n_rx_packets); return n_rx_packets; } @@ -1946,15 +1949,15 @@ vhost_user_input (vlib_main_t * vm, { vhost_user_main_t *vum = &vhost_user_main; uword n_rx_packets = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); vhost_iface_and_queue_t *vhiq; vhost_user_intf_t *vui; vhost_cpu_t *vhc; - vhc = &vum->cpus[cpu_index]; + vhc = &vum->cpus[thread_index]; if (PREDICT_TRUE (vhc->operation_mode == VHOST_USER_POLLING_MODE)) { - vec_foreach (vhiq, vum->cpus[cpu_index].rx_queues) + vec_foreach (vhiq, vum->cpus[thread_index].rx_queues) { vui = &vum->vhost_user_interfaces[vhiq->vhost_iface_index]; n_rx_packets += vhost_user_if_input (vm, vum, vui, vhiq->qid, node); @@ -2096,7 +2099,7 @@ vhost_user_tx (vlib_main_t * vm, vhost_user_vring_t *rxvq; u16 qsz_mask; u8 error; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 map_hint = 0; u8 retry = 8; u16 copy_len; @@ -2116,7 +2119,7 @@ vhost_user_tx (vlib_main_t * vm, qid = VHOST_VRING_IDX_RX (*vec_elt_at_index - (vui->per_cpu_tx_qid, os_get_cpu_number ())); + (vui->per_cpu_tx_qid, vlib_get_thread_index ())); rxvq = &vui->vrings[qid]; if (PREDICT_FALSE (vui->use_tx_spinlock)) vhost_user_vring_lock (vui, qid); @@ -2143,10 +2146,10 @@ retry: if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - vum->cpus[cpu_index].current_trace = + vum->cpus[thread_index].current_trace = vlib_add_trace (vm, node, b0, - sizeof (*vum->cpus[cpu_index].current_trace)); - vhost_user_tx_trace (vum->cpus[cpu_index].current_trace, + sizeof (*vum->cpus[thread_index].current_trace)); + vhost_user_tx_trace (vum->cpus[thread_index].current_trace, vui, qid / 2, b0, rxvq); } @@ -2188,14 +2191,14 @@ retry: { // Get a header from the header array virtio_net_hdr_mrg_rxbuf_t *hdr = - &vum->cpus[cpu_index].tx_headers[tx_headers_len]; + &vum->cpus[thread_index].tx_headers[tx_headers_len]; tx_headers_len++; hdr->hdr.flags = 0; hdr->hdr.gso_type = 0; hdr->num_buffers = 1; //This is local, no need to check // Prepare a copy order executed later for the header - vhost_copy_t *cpy = &vum->cpus[cpu_index].copy[copy_len]; + vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len]; copy_len++; cpy->len = vui->virtio_net_hdr_sz; cpy->dst = buffer_map_addr; @@ -2220,7 +2223,7 @@ retry: else if (vui->virtio_net_hdr_sz == 12) //MRG is available { virtio_net_hdr_mrg_rxbuf_t *hdr = - &vum->cpus[cpu_index].tx_headers[tx_headers_len - 1]; + &vum->cpus[thread_index].tx_headers[tx_headers_len - 1]; //Move from available to used buffer rxvq->used->ring[rxvq->last_used_idx & qsz_mask].id = @@ -2282,7 +2285,7 @@ retry: } { - vhost_copy_t *cpy = &vum->cpus[cpu_index].copy[copy_len]; + vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len]; copy_len++; cpy->len = bytes_left; cpy->len = (cpy->len > buffer_len) ? buffer_len : cpy->len; @@ -2325,8 +2328,8 @@ retry: if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - vum->cpus[cpu_index].current_trace->hdr = - vum->cpus[cpu_index].tx_headers[tx_headers_len - 1]; + vum->cpus[thread_index].current_trace->hdr = + vum->cpus[thread_index].tx_headers[tx_headers_len - 1]; } n_left--; //At the end for error counting when 'goto done' is invoked @@ -2336,7 +2339,7 @@ retry: done: //Do the memory copies if (PREDICT_FALSE - (vhost_user_tx_copy (vui, vum->cpus[cpu_index].copy, + (vhost_user_tx_copy (vui, vum->cpus[thread_index].copy, copy_len, &map_hint))) { clib_warning ("Memory mapping error on interface hw_if_index=%d " @@ -2386,7 +2389,7 @@ done3: vlib_increment_simple_counter (vnet_main.interface_main.sw_if_counters + VNET_INTERFACE_COUNTER_DROP, - os_get_cpu_number (), vui->sw_if_index, n_left); + vlib_get_thread_index (), vui->sw_if_index, n_left); } vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors); @@ -2773,11 +2776,11 @@ vhost_user_send_interrupt_process (vlib_main_t * vm, case ~0: vec_foreach (vhc, vum->cpus) { - u32 cpu_index = vhc - vum->cpus; + u32 thread_index = vhc - vum->cpus; f64 next_timeout; next_timeout = timeout; - vec_foreach (vhiq, vum->cpus[cpu_index].rx_queues) + vec_foreach (vhiq, vum->cpus[thread_index].rx_queues) { vui = &vum->vhost_user_interfaces[vhiq->vhost_iface_index]; vhost_user_vring_t *rxvq = diff --git a/src/vnet/dpo/lookup_dpo.c b/src/vnet/dpo/lookup_dpo.c index e94e871c..97ad0a44 100644 --- a/src/vnet/dpo/lookup_dpo.c +++ b/src/vnet/dpo/lookup_dpo.c @@ -266,7 +266,7 @@ lookup_dpo_ip4_inline (vlib_main_t * vm, int table_from_interface) { u32 n_left_from, next_index, * from, * to_next; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters; from = vlib_frame_vector_args (from_frame); @@ -407,10 +407,10 @@ lookup_dpo_ip4_inline (vlib_main_t * vm, vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, b1)); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -511,7 +511,7 @@ lookup_dpo_ip4_inline (vlib_main_t * vm, vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -606,7 +606,7 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, { vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters; u32 n_left_from, next_index, * from, * to_next; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -749,10 +749,10 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, b1)); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -853,7 +853,7 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -930,7 +930,7 @@ lookup_dpo_mpls_inline (vlib_main_t * vm, int table_from_interface) { u32 n_left_from, next_index, * from, * to_next; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters; from = vlib_frame_vector_args (from_frame); @@ -994,7 +994,7 @@ lookup_dpo_mpls_inline (vlib_main_t * vm, vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) diff --git a/src/vnet/dpo/replicate_dpo.c b/src/vnet/dpo/replicate_dpo.c index a9f334be..e25ceae9 100644 --- a/src/vnet/dpo/replicate_dpo.c +++ b/src/vnet/dpo/replicate_dpo.c @@ -627,7 +627,7 @@ replicate_inline (vlib_main_t * vm, vlib_combined_counter_main_t * cm = &replicate_main.repm_counters; replicate_main_t * rm = &replicate_main; u32 n_left_from, * from, * to_next, next_index; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -657,12 +657,12 @@ replicate_inline (vlib_main_t * vm, rep0 = replicate_get(repi0); vlib_increment_combined_counter( - cm, cpu_index, repi0, 1, + cm, thread_index, repi0, 1, vlib_buffer_length_in_chain(vm, b0)); - vec_validate (rm->clones[cpu_index], rep0->rep_n_buckets - 1); + vec_validate (rm->clones[thread_index], rep0->rep_n_buckets - 1); - num_cloned = vlib_buffer_clone (vm, bi0, rm->clones[cpu_index], rep0->rep_n_buckets, 128); + num_cloned = vlib_buffer_clone (vm, bi0, rm->clones[thread_index], rep0->rep_n_buckets, 128); if (num_cloned != rep0->rep_n_buckets) { @@ -673,7 +673,7 @@ replicate_inline (vlib_main_t * vm, for (bucket = 0; bucket < num_cloned; bucket++) { - ci0 = rm->clones[cpu_index][bucket]; + ci0 = rm->clones[thread_index][bucket]; c0 = vlib_get_buffer(vm, ci0); to_next[0] = ci0; @@ -700,7 +700,7 @@ replicate_inline (vlib_main_t * vm, vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); } } - vec_reset_length (rm->clones[cpu_index]); + vec_reset_length (rm->clones[thread_index]); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index ee757505..c74a097e 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -1771,7 +1771,7 @@ set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t * a) { vnet_main_t *vm = vnet_get_main (); - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); if (a->flags & ETHERNET_ARP_ARGS_REMOVE) vnet_arp_unset_ip4_over_ethernet_internal (vm, a); diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c index 9894e3c8..335e3f9f 100644 --- a/src/vnet/ethernet/interface.c +++ b/src/vnet/ethernet/interface.c @@ -362,7 +362,7 @@ simulated_ethernet_interface_tx (vlib_main_t * vm, u32 next_index = VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT; u32 i, next_node_index, bvi_flag, sw_if_index; u32 n_pkts = 0, n_bytes = 0; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; vlib_node_main_t *nm = &vm->node_main; @@ -420,8 +420,9 @@ simulated_ethernet_interface_tx (vlib_main_t * vm, /* increment TX interface stat */ vlib_increment_combined_counter (im->combined_sw_if_counters + - VNET_INTERFACE_COUNTER_TX, cpu_index, - sw_if_index, n_pkts, n_bytes); + VNET_INTERFACE_COUNTER_TX, + thread_index, sw_if_index, n_pkts, + n_bytes); } return n_left_from; diff --git a/src/vnet/ethernet/node.c b/src/vnet/ethernet/node.c index b699e381..f7787ed2 100755 --- a/src/vnet/ethernet/node.c +++ b/src/vnet/ethernet/node.c @@ -291,7 +291,7 @@ ethernet_input_inline (vlib_main_t * vm, vlib_node_runtime_t *error_node; u32 n_left_from, next_index, *from, *to_next; u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 cached_sw_if_index = ~0; u32 cached_is_l2 = 0; /* shut up gcc */ vnet_hw_interface_t *hi = NULL; /* used for main interface only */ @@ -510,7 +510,7 @@ ethernet_input_inline (vlib_main_t * vm, interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, new_sw_if_index0, 1, len0); if (new_sw_if_index1 != old_sw_if_index1 @@ -519,7 +519,7 @@ ethernet_input_inline (vlib_main_t * vm, interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, new_sw_if_index1, 1, len1); @@ -530,7 +530,7 @@ ethernet_input_inline (vlib_main_t * vm, vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = stats_n_bytes = 0; @@ -696,13 +696,13 @@ ethernet_input_inline (vlib_main_t * vm, vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, new_sw_if_index0, 1, len0); + thread_index, new_sw_if_index0, 1, len0); if (stats_n_packets > 0) { vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = stats_n_bytes = 0; } @@ -734,7 +734,7 @@ ethernet_input_inline (vlib_main_t * vm, vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } diff --git a/src/vnet/gre/node.c b/src/vnet/gre/node.c index 2683586e..acf15f24 100644 --- a/src/vnet/gre/node.c +++ b/src/vnet/gre/node.c @@ -75,7 +75,7 @@ gre_input (vlib_main_t * vm, u64 cached_tunnel_key6[4]; u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u32 len; vnet_interface_main_t *im = &gm->vnet_main->interface_main; @@ -257,7 +257,7 @@ gre_input (vlib_main_t * vm, len = vlib_buffer_length_in_chain (vm, b0); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, tunnel_sw_if_index, 1 /* packets */, len /* bytes */); @@ -324,7 +324,7 @@ drop0: len = vlib_buffer_length_in_chain (vm, b1); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, tunnel_sw_if_index, 1 /* packets */, len /* bytes */); @@ -502,7 +502,7 @@ drop1: len = vlib_buffer_length_in_chain (vm, b0); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, + thread_index, tunnel_sw_if_index, 1 /* packets */, len /* bytes */); diff --git a/src/vnet/interface.h b/src/vnet/interface.h index a1ea2d61..08f08b10 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -468,7 +468,7 @@ typedef struct vnet_hw_interface_t u32 input_node_index; /* input node cpu index by queue */ - u32 *input_node_cpu_index_by_queue; + u32 *input_node_thread_index_by_queue; } vnet_hw_interface_t; diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index 03f2cdca..663dc309 100644 --- a/src/vnet/interface_output.c +++ b/src/vnet/interface_output.c @@ -196,7 +196,7 @@ slow_path (vlib_main_t * vm, */ static_always_inline void incr_output_stats (vnet_main_t * vnm, - u32 cpu_index, + u32 thread_index, u32 length, u32 sw_if_index, u32 * last_sw_if_index, u32 * n_packets, u32 * n_bytes) @@ -216,7 +216,7 @@ incr_output_stats (vnet_main_t * vnm, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, + thread_index, *last_sw_if_index, *n_packets, *n_bytes); } @@ -240,7 +240,7 @@ vnet_interface_output_node_flatten (vlib_main_t * vm, u32 n_left_to_tx, *from, *from_end, *to_tx; u32 n_bytes, n_buffers, n_packets; u32 last_sw_if_index; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; n_buffers = frame->n_vectors; @@ -266,7 +266,7 @@ vnet_interface_output_node_flatten (vlib_main_t * vm, cm = vec_elt_at_index (vnm->interface_main.sw_if_counters, VNET_INTERFACE_COUNTER_TX_ERROR); - vlib_increment_simple_counter (cm, cpu_index, + vlib_increment_simple_counter (cm, thread_index, rt->sw_if_index, n_buffers); return vlib_error_drop_buffers (vm, node, from, /* buffer stride */ 1, @@ -341,18 +341,18 @@ vnet_interface_output_node_flatten (vlib_main_t * vm, from += 1; to_tx += n_buffers; n_left_to_tx -= n_buffers; - incr_output_stats (vnm, cpu_index, n_slow_bytes, + incr_output_stats (vnm, thread_index, n_slow_bytes, vnet_buffer (b)->sw_if_index[VLIB_TX], &last_sw_if_index, &n_packets, &n_bytes); } } else { - incr_output_stats (vnm, cpu_index, + incr_output_stats (vnm, thread_index, vlib_buffer_length_in_chain (vm, b0), vnet_buffer (b0)->sw_if_index[VLIB_TX], &last_sw_if_index, &n_packets, &n_bytes); - incr_output_stats (vnm, cpu_index, + incr_output_stats (vnm, thread_index, vlib_buffer_length_in_chain (vm, b0), vnet_buffer (b1)->sw_if_index[VLIB_TX], &last_sw_if_index, &n_packets, &n_bytes); @@ -396,7 +396,7 @@ vnet_interface_output_node_flatten (vlib_main_t * vm, to_tx += n_buffers; n_left_to_tx -= n_buffers; } - incr_output_stats (vnm, cpu_index, + incr_output_stats (vnm, thread_index, vlib_buffer_length_in_chain (vm, b0), vnet_buffer (b0)->sw_if_index[VLIB_TX], &last_sw_if_index, &n_packets, &n_bytes); @@ -408,7 +408,7 @@ vnet_interface_output_node_flatten (vlib_main_t * vm, } /* Final update of interface stats. */ - incr_output_stats (vnm, cpu_index, 0, ~0, /* ~0 will flush stats */ + incr_output_stats (vnm, thread_index, 0, ~0, /* ~0 will flush stats */ &last_sw_if_index, &n_packets, &n_bytes); return n_buffers; @@ -428,7 +428,7 @@ vnet_interface_output_node (vlib_main_t * vm, u32 n_left_to_tx, *from, *from_end, *to_tx; u32 n_bytes, n_buffers, n_packets; u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; vnet_interface_main_t *im = &vnm->interface_main; u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX; u32 current_config_index = ~0; @@ -458,7 +458,7 @@ vnet_interface_output_node (vlib_main_t * vm, cm = vec_elt_at_index (vnm->interface_main.sw_if_counters, VNET_INTERFACE_COUNTER_TX_ERROR); - vlib_increment_simple_counter (cm, cpu_index, + vlib_increment_simple_counter (cm, thread_index, rt->sw_if_index, n_buffers); return vlib_error_drop_buffers (vm, node, from, @@ -558,7 +558,7 @@ vnet_interface_output_node (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, tx_swif0, 1, + thread_index, tx_swif0, 1, n_bytes_b0); } @@ -567,7 +567,7 @@ vnet_interface_output_node (vlib_main_t * vm, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, tx_swif1, 1, + thread_index, tx_swif1, 1, n_bytes_b1); } @@ -576,7 +576,7 @@ vnet_interface_output_node (vlib_main_t * vm, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, tx_swif2, 1, + thread_index, tx_swif2, 1, n_bytes_b2); } if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index)) @@ -584,7 +584,7 @@ vnet_interface_output_node (vlib_main_t * vm, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, tx_swif3, 1, + thread_index, tx_swif3, 1, n_bytes_b3); } } @@ -623,7 +623,7 @@ vnet_interface_output_node (vlib_main_t * vm, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, tx_swif0, 1, + thread_index, tx_swif0, 1, n_bytes_b0); } } @@ -634,7 +634,7 @@ vnet_interface_output_node (vlib_main_t * vm, /* Update main interface stats. */ vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, + thread_index, rt->sw_if_index, n_packets, n_bytes); return n_buffers; } @@ -893,7 +893,7 @@ process_drop_punt (vlib_main_t * vm, u32 current_sw_if_index, n_errors_current_sw_if_index; u64 current_counter; vlib_simple_counter_main_t *cm; - u32 cpu_index = vm->cpu_index; + u32 thread_index = vm->thread_index; static vlib_error_t memory[VNET_ERROR_N_DISPOSITION]; static char memory_init[VNET_ERROR_N_DISPOSITION]; @@ -965,19 +965,19 @@ process_drop_punt (vlib_main_t * vm, current_counter -= 2; n_errors_current_sw_if_index -= 2; - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1); /* Increment super-interface drop/punt counters for sub-interfaces. */ sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0); vlib_increment_simple_counter - (cm, cpu_index, sw_if0->sup_sw_if_index, + (cm, thread_index, sw_if0->sup_sw_if_index, sw_if0->sup_sw_if_index != sw_if_index0); sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1); vlib_increment_simple_counter - (cm, cpu_index, sw_if1->sup_sw_if_index, + (cm, thread_index, sw_if1->sup_sw_if_index, sw_if1->sup_sw_if_index != sw_if_index1); em->counters[current_counter_index] = current_counter; @@ -1013,11 +1013,12 @@ process_drop_punt (vlib_main_t * vm, sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; /* Increment drop/punt counters. */ - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); /* Increment super-interface drop/punt counters for sub-interfaces. */ sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0); - vlib_increment_simple_counter (cm, cpu_index, sw_if0->sup_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, + sw_if0->sup_sw_if_index, sw_if0->sup_sw_if_index != sw_if_index0); if (PREDICT_FALSE (e0 != current_error)) @@ -1041,12 +1042,12 @@ process_drop_punt (vlib_main_t * vm, { vnet_sw_interface_t *si; - vlib_increment_simple_counter (cm, cpu_index, current_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, current_sw_if_index, n_errors_current_sw_if_index); si = vnet_get_sw_interface (vnm, current_sw_if_index); if (si->sup_sw_if_index != current_sw_if_index) - vlib_increment_simple_counter (cm, cpu_index, si->sup_sw_if_index, + vlib_increment_simple_counter (cm, thread_index, si->sup_sw_if_index, n_errors_current_sw_if_index); } diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index ee1703e7..fdfe7f63 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -75,7 +75,7 @@ ip4_lookup_inline (vlib_main_t * vm, vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -292,19 +292,19 @@ ip4_lookup_inline (vlib_main_t * vm, vnet_buffer (p3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lb_index0, 1, + (cm, thread_index, lb_index0, 1, vlib_buffer_length_in_chain (vm, p0) + sizeof (ethernet_header_t)); vlib_increment_combined_counter - (cm, cpu_index, lb_index1, 1, + (cm, thread_index, lb_index1, 1, vlib_buffer_length_in_chain (vm, p1) + sizeof (ethernet_header_t)); vlib_increment_combined_counter - (cm, cpu_index, lb_index2, 1, + (cm, thread_index, lb_index2, 1, vlib_buffer_length_in_chain (vm, p2) + sizeof (ethernet_header_t)); vlib_increment_combined_counter - (cm, cpu_index, lb_index3, 1, + (cm, thread_index, lb_index3, 1, vlib_buffer_length_in_chain (vm, p3) + sizeof (ethernet_header_t)); @@ -392,7 +392,7 @@ ip4_lookup_inline (vlib_main_t * vm, vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); from += 1; to_next += 1; @@ -479,7 +479,7 @@ ip4_load_balance (vlib_main_t * vm, vlib_combined_counter_main_t *cm = &load_balance_main.lbm_via_counters; u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -584,9 +584,9 @@ ip4_load_balance (vlib_main_t * vm, vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); vlib_validate_buffer_enqueue_x2 (vm, node, next, to_next, n_left_to_next, @@ -639,7 +639,7 @@ ip4_load_balance (vlib_main_t * vm, vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_validate_buffer_enqueue_x1 (vm, node, next, to_next, n_left_to_next, @@ -2330,7 +2330,7 @@ ip4_rewrite_inline (vlib_main_t * vm, n_left_from = frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -2379,9 +2379,9 @@ ip4_rewrite_inline (vlib_main_t * vm, if (do_counters) { vlib_prefetch_combined_counter (&adjacency_counters, - cpu_index, adj_index0); + thread_index, adj_index0); vlib_prefetch_combined_counter (&adjacency_counters, - cpu_index, adj_index1); + thread_index, adj_index1); } ip0 = vlib_buffer_get_current (p0); @@ -2527,13 +2527,13 @@ ip4_rewrite_inline (vlib_main_t * vm, { vlib_increment_combined_counter (&adjacency_counters, - cpu_index, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); vlib_increment_combined_counter (&adjacency_counters, - cpu_index, + thread_index, adj_index1, 1, vlib_buffer_length_in_chain (vm, p1) + rw_len1); } @@ -2618,7 +2618,7 @@ ip4_rewrite_inline (vlib_main_t * vm, if (do_counters) vlib_prefetch_combined_counter (&adjacency_counters, - cpu_index, adj_index0); + thread_index, adj_index0); /* Guess we are only writing on simple Ethernet header. */ vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t)); @@ -2637,7 +2637,7 @@ ip4_rewrite_inline (vlib_main_t * vm, if (do_counters) vlib_increment_combined_counter (&adjacency_counters, - cpu_index, adj_index0, 1, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); /* Check MTU of outgoing interface. */ diff --git a/src/vnet/ip/ip4_input.c b/src/vnet/ip/ip4_input.c index ba200a9f..3b08f4b0 100644 --- a/src/vnet/ip/ip4_input.c +++ b/src/vnet/ip/ip4_input.c @@ -85,7 +85,7 @@ ip4_input_inline (vlib_main_t * vm, vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, ip4_input_node.index); vlib_simple_counter_main_t *cm; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -178,8 +178,8 @@ ip4_input_inline (vlib_main_t * vm, vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1); /* Punt packets with options or wrong version. */ if (PREDICT_FALSE (ip0->ip_version_and_header_length != 0x45)) @@ -299,7 +299,7 @@ ip4_input_inline (vlib_main_t * vm, vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); /* Punt packets with options or wrong version. */ if (PREDICT_FALSE (ip0->ip_version_and_header_length != 0x45)) diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index c120f12c..c2fc4f87 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -74,7 +74,7 @@ ip6_lookup_inline (vlib_main_t * vm, vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -185,9 +185,9 @@ ip6_lookup_inline (vlib_main_t * vm, vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); from += 2; to_next += 2; @@ -291,7 +291,7 @@ ip6_lookup_inline (vlib_main_t * vm, vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); from += 1; to_next += 1; @@ -703,7 +703,7 @@ ip6_load_balance (vlib_main_t * vm, vlib_combined_counter_main_t *cm = &load_balance_main.lbm_via_counters; u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); ip6_main_t *im = &ip6_main; from = vlib_frame_vector_args (frame); @@ -824,9 +824,9 @@ ip6_load_balance (vlib_main_t * vm, vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); vlib_validate_buffer_enqueue_x2 (vm, node, next, to_next, n_left_to_next, @@ -886,7 +886,7 @@ ip6_load_balance (vlib_main_t * vm, } vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_validate_buffer_enqueue_x1 (vm, node, next, to_next, n_left_to_next, @@ -1897,7 +1897,7 @@ ip6_rewrite_inline (vlib_main_t * vm, n_left_from = frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -2019,11 +2019,11 @@ ip6_rewrite_inline (vlib_main_t * vm, { vlib_increment_combined_counter (&adjacency_counters, - cpu_index, adj_index0, 1, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); vlib_increment_combined_counter (&adjacency_counters, - cpu_index, adj_index1, 1, + thread_index, adj_index1, 1, vlib_buffer_length_in_chain (vm, p1) + rw_len1); } @@ -2156,7 +2156,7 @@ ip6_rewrite_inline (vlib_main_t * vm, { vlib_increment_combined_counter (&adjacency_counters, - cpu_index, adj_index0, 1, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); } diff --git a/src/vnet/ip/ip6_input.c b/src/vnet/ip/ip6_input.c index 20306088..ffdc4727 100644 --- a/src/vnet/ip/ip6_input.c +++ b/src/vnet/ip/ip6_input.c @@ -82,7 +82,7 @@ ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, ip6_input_node.index); vlib_simple_counter_main_t *cm; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -171,8 +171,8 @@ ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1); error0 = error1 = IP6_ERROR_NONE; @@ -270,7 +270,7 @@ ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); error0 = IP6_ERROR_NONE; /* Version != 6? Drop it. */ diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 5d1fb6f8..2af546df 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -581,7 +581,7 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, u32 next_index; pending_resolution_t *pr, *mc; - if (os_get_cpu_number ()) + if (vlib_get_thread_index ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, 1 /* set new neighbor */ , is_static, @@ -722,7 +722,7 @@ vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm, uword *p; int rv = 0; - if (os_get_cpu_number ()) + if (vlib_get_thread_index ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, 0 /* unset */ , 0, 0); diff --git a/src/vnet/ipsec/esp.h b/src/vnet/ipsec/esp.h index 50cac806..799003b9 100644 --- a/src/vnet/ipsec/esp.h +++ b/src/vnet/ipsec/esp.h @@ -282,8 +282,8 @@ hmac_calc (ipsec_integ_alg_t alg, u8 * data, int data_len, u8 * signature, u8 use_esn, u32 seq_hi) { esp_main_t *em = &esp_main; - u32 cpu_index = os_get_cpu_number (); - HMAC_CTX *ctx = &(em->per_thread_data[cpu_index].hmac_ctx); + u32 thread_index = vlib_get_thread_index (); + HMAC_CTX *ctx = &(em->per_thread_data[thread_index].hmac_ctx); const EVP_MD *md = NULL; unsigned int len; @@ -292,10 +292,10 @@ hmac_calc (ipsec_integ_alg_t alg, if (PREDICT_FALSE (em->esp_integ_algs[alg].md == 0)) return 0; - if (PREDICT_FALSE (alg != em->per_thread_data[cpu_index].last_integ_alg)) + if (PREDICT_FALSE (alg != em->per_thread_data[thread_index].last_integ_alg)) { md = em->esp_integ_algs[alg].md; - em->per_thread_data[cpu_index].last_integ_alg = alg; + em->per_thread_data[thread_index].last_integ_alg = alg; } HMAC_Init (ctx, key, key_len, md); diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c index 7289b260..925d2b45 100644 --- a/src/vnet/ipsec/esp_decrypt.c +++ b/src/vnet/ipsec/esp_decrypt.c @@ -85,8 +85,8 @@ esp_decrypt_aes_cbc (ipsec_crypto_alg_t alg, u8 * in, u8 * out, size_t in_len, u8 * key, u8 * iv) { esp_main_t *em = &esp_main; - u32 cpu_index = os_get_cpu_number (); - EVP_CIPHER_CTX *ctx = &(em->per_thread_data[cpu_index].decrypt_ctx); + u32 thread_index = vlib_get_thread_index (); + EVP_CIPHER_CTX *ctx = &(em->per_thread_data[thread_index].decrypt_ctx); const EVP_CIPHER *cipher = NULL; int out_len; @@ -95,10 +95,11 @@ esp_decrypt_aes_cbc (ipsec_crypto_alg_t alg, if (PREDICT_FALSE (em->esp_crypto_algs[alg].type == 0)) return; - if (PREDICT_FALSE (alg != em->per_thread_data[cpu_index].last_decrypt_alg)) + if (PREDICT_FALSE + (alg != em->per_thread_data[thread_index].last_decrypt_alg)) { cipher = em->esp_crypto_algs[alg].type; - em->per_thread_data[cpu_index].last_decrypt_alg = alg; + em->per_thread_data[thread_index].last_decrypt_alg = alg; } EVP_DecryptInit_ex (ctx, cipher, NULL, key, iv); @@ -117,11 +118,11 @@ esp_decrypt_node_fn (vlib_main_t * vm, u32 *recycle = 0; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); ipsec_alloc_empty_buffers (vm, im); - u32 *empty_buffers = im->empty_buffers[cpu_index]; + u32 *empty_buffers = im->empty_buffers[thread_index]; if (PREDICT_FALSE (vec_len (empty_buffers) < n_left_from)) { diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c index 44ae2297..b2bc4e0b 100644 --- a/src/vnet/ipsec/esp_encrypt.c +++ b/src/vnet/ipsec/esp_encrypt.c @@ -88,8 +88,8 @@ esp_encrypt_aes_cbc (ipsec_crypto_alg_t alg, u8 * in, u8 * out, size_t in_len, u8 * key, u8 * iv) { esp_main_t *em = &esp_main; - u32 cpu_index = os_get_cpu_number (); - EVP_CIPHER_CTX *ctx = &(em->per_thread_data[cpu_index].encrypt_ctx); + u32 thread_index = vlib_get_thread_index (); + EVP_CIPHER_CTX *ctx = &(em->per_thread_data[thread_index].encrypt_ctx); const EVP_CIPHER *cipher = NULL; int out_len; @@ -98,10 +98,11 @@ esp_encrypt_aes_cbc (ipsec_crypto_alg_t alg, if (PREDICT_FALSE (em->esp_crypto_algs[alg].type == IPSEC_CRYPTO_ALG_NONE)) return; - if (PREDICT_FALSE (alg != em->per_thread_data[cpu_index].last_encrypt_alg)) + if (PREDICT_FALSE + (alg != em->per_thread_data[thread_index].last_encrypt_alg)) { cipher = em->esp_crypto_algs[alg].type; - em->per_thread_data[cpu_index].last_encrypt_alg = alg; + em->per_thread_data[thread_index].last_encrypt_alg = alg; } EVP_EncryptInit_ex (ctx, cipher, NULL, key, iv); @@ -119,11 +120,11 @@ esp_encrypt_node_fn (vlib_main_t * vm, n_left_from = from_frame->n_vectors; ipsec_main_t *im = &ipsec_main; u32 *recycle = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); ipsec_alloc_empty_buffers (vm, im); - u32 *empty_buffers = im->empty_buffers[cpu_index]; + u32 *empty_buffers = im->empty_buffers[thread_index]; if (PREDICT_FALSE (vec_len (empty_buffers) < n_left_from)) { diff --git a/src/vnet/ipsec/ikev2.c b/src/vnet/ipsec/ikev2.c index 2c1074d8..3f9978a7 100644 --- a/src/vnet/ipsec/ikev2.c +++ b/src/vnet/ipsec/ikev2.c @@ -303,16 +303,16 @@ static void ikev2_delete_sa (ikev2_sa_t * sa) { ikev2_main_t *km = &ikev2_main; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); uword *p; ikev2_sa_free_all_vec (sa); - p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi); + p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi); if (p) { - hash_unset (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi); - pool_put (km->per_thread_data[cpu_index].sas, sa); + hash_unset (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi); + pool_put (km->per_thread_data[thread_index].sas, sa); } } @@ -776,29 +776,31 @@ ikev2_initial_contact_cleanup (ikev2_sa_t * sa) ikev2_sa_t *tmp; u32 i, *delete = 0; ikev2_child_sa_t *c; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); if (!sa->initial_contact) return; /* find old IKE SAs with the same authenticated identity */ /* *INDENT-OFF* */ - pool_foreach (tmp, km->per_thread_data[cpu_index].sas, ({ + pool_foreach (tmp, km->per_thread_data[thread_index].sas, ({ if (tmp->i_id.type != sa->i_id.type || vec_len(tmp->i_id.data) != vec_len(sa->i_id.data) || memcmp(sa->i_id.data, tmp->i_id.data, vec_len(sa->i_id.data))) continue; if (sa->rspi != tmp->rspi) - vec_add1(delete, tmp - km->per_thread_data[cpu_index].sas); + vec_add1(delete, tmp - km->per_thread_data[thread_index].sas); })); /* *INDENT-ON* */ for (i = 0; i < vec_len (delete); i++) { - tmp = pool_elt_at_index (km->per_thread_data[cpu_index].sas, delete[i]); - vec_foreach (c, tmp->childs) - ikev2_delete_tunnel_interface (km->vnet_main, tmp, c); + tmp = + pool_elt_at_index (km->per_thread_data[thread_index].sas, delete[i]); + vec_foreach (c, + tmp->childs) ikev2_delete_tunnel_interface (km->vnet_main, + tmp, c); ikev2_delete_sa (tmp); } @@ -1922,10 +1924,10 @@ ikev2_retransmit_sa_init (ike_header_t * ike, { ikev2_main_t *km = &ikev2_main; ikev2_sa_t *sa; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); /* *INDENT-OFF* */ - pool_foreach (sa, km->per_thread_data[cpu_index].sas, ({ + pool_foreach (sa, km->per_thread_data[thread_index].sas, ({ if (sa->ispi == clib_net_to_host_u64(ike->ispi) && sa->iaddr.as_u32 == iaddr.as_u32 && sa->raddr.as_u32 == raddr.as_u32) @@ -2036,7 +2038,7 @@ ikev2_node_fn (vlib_main_t * vm, u32 n_left_from, *from, *to_next; ikev2_next_t next_index; ikev2_main_t *km = &ikev2_main; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -2134,11 +2136,14 @@ ikev2_node_fn (vlib_main_t * vm, if (sa0->state == IKEV2_STATE_SA_INIT) { /* add SA to the pool */ - pool_get (km->per_thread_data[cpu_index].sas, sa0); + pool_get (km->per_thread_data[thread_index].sas, + sa0); clib_memcpy (sa0, &sa, sizeof (*sa0)); - hash_set (km->per_thread_data[cpu_index].sa_by_rspi, + hash_set (km-> + per_thread_data[thread_index].sa_by_rspi, sa0->rspi, - sa0 - km->per_thread_data[cpu_index].sas); + sa0 - + km->per_thread_data[thread_index].sas); } else { @@ -2169,11 +2174,11 @@ ikev2_node_fn (vlib_main_t * vm, if (sa0->state == IKEV2_STATE_SA_INIT) { /* add SA to the pool */ - pool_get (km->per_thread_data[cpu_index].sas, sa0); + pool_get (km->per_thread_data[thread_index].sas, sa0); clib_memcpy (sa0, &sa, sizeof (*sa0)); - hash_set (km->per_thread_data[cpu_index].sa_by_rspi, + hash_set (km->per_thread_data[thread_index].sa_by_rspi, sa0->rspi, - sa0 - km->per_thread_data[cpu_index].sas); + sa0 - km->per_thread_data[thread_index].sas); } else { @@ -2184,12 +2189,13 @@ ikev2_node_fn (vlib_main_t * vm, else if (ike0->exchange == IKEV2_EXCHANGE_IKE_AUTH) { uword *p; - p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, + p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, clib_net_to_host_u64 (ike0->rspi)); if (p) { - sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas, - p[0]); + sa0 = + pool_elt_at_index (km->per_thread_data[thread_index].sas, + p[0]); r = ikev2_retransmit_resp (sa0, ike0); if (r == 1) @@ -2240,12 +2246,13 @@ ikev2_node_fn (vlib_main_t * vm, else if (ike0->exchange == IKEV2_EXCHANGE_INFORMATIONAL) { uword *p; - p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, + p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, clib_net_to_host_u64 (ike0->rspi)); if (p) { - sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas, - p[0]); + sa0 = + pool_elt_at_index (km->per_thread_data[thread_index].sas, + p[0]); r = ikev2_retransmit_resp (sa0, ike0); if (r == 1) @@ -2305,12 +2312,13 @@ ikev2_node_fn (vlib_main_t * vm, else if (ike0->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA) { uword *p; - p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, + p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, clib_net_to_host_u64 (ike0->rspi)); if (p) { - sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas, - p[0]); + sa0 = + pool_elt_at_index (km->per_thread_data[thread_index].sas, + p[0]); r = ikev2_retransmit_resp (sa0, ike0); if (r == 1) diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h index 58f0f145..c884e360 100644 --- a/src/vnet/ipsec/ipsec.h +++ b/src/vnet/ipsec/ipsec.h @@ -324,21 +324,21 @@ int ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, always_inline void ipsec_alloc_empty_buffers (vlib_main_t * vm, ipsec_main_t * im) { - u32 cpu_index = os_get_cpu_number (); - uword l = vec_len (im->empty_buffers[cpu_index]); + u32 thread_index = vlib_get_thread_index (); + uword l = vec_len (im->empty_buffers[thread_index]); uword n_alloc = 0; if (PREDICT_FALSE (l < VLIB_FRAME_SIZE)) { - if (!im->empty_buffers[cpu_index]) + if (!im->empty_buffers[thread_index]) { - vec_alloc (im->empty_buffers[cpu_index], 2 * VLIB_FRAME_SIZE); + vec_alloc (im->empty_buffers[thread_index], 2 * VLIB_FRAME_SIZE); } - n_alloc = vlib_buffer_alloc (vm, im->empty_buffers[cpu_index] + l, + n_alloc = vlib_buffer_alloc (vm, im->empty_buffers[thread_index] + l, 2 * VLIB_FRAME_SIZE - l); - _vec_len (im->empty_buffers[cpu_index]) = l + n_alloc; + _vec_len (im->empty_buffers[thread_index]) = l + n_alloc; } } diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c index dc882004..ed124894 100644 --- a/src/vnet/ipsec/ipsec_if.c +++ b/src/vnet/ipsec/ipsec_if.c @@ -99,7 +99,7 @@ static int ipsec_add_del_tunnel_if_rpc_callback (ipsec_add_del_tunnel_args_t * a) { vnet_main_t *vnm = vnet_get_main (); - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); return ipsec_add_del_tunnel_if_internal (vnm, a); } diff --git a/src/vnet/l2/l2_bvi.h b/src/vnet/l2/l2_bvi.h index dd1130a6..e21a1616 100644 --- a/src/vnet/l2/l2_bvi.h +++ b/src/vnet/l2/l2_bvi.h @@ -97,7 +97,7 @@ l2_to_bvi (vlib_main_t * vlib_main, vlib_increment_combined_counter (vnet_main->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - vlib_main->cpu_index, + vlib_main->thread_index, vnet_buffer (b0)->sw_if_index[VLIB_RX], 1, vlib_buffer_length_in_chain (vlib_main, b0)); return TO_BVI_ERR_OK; diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index 041ff38d..e5d6878a 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -117,7 +117,7 @@ typedef enum static_always_inline void classify_and_dispatch (vlib_main_t * vm, vlib_node_runtime_t * node, - u32 cpu_index, + u32 thread_index, l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0) { /* @@ -237,7 +237,7 @@ l2input_node_inline (vlib_main_t * vm, u32 n_left_from, *from, *to_next; l2input_next_t next_index; l2input_main_t *msm = &l2input_main; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* number of packets to process */ @@ -350,10 +350,10 @@ l2input_node_inline (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 4); - classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0); - classify_and_dispatch (vm, node, cpu_index, msm, b1, &next1); - classify_and_dispatch (vm, node, cpu_index, msm, b2, &next2); - classify_and_dispatch (vm, node, cpu_index, msm, b3, &next3); + classify_and_dispatch (vm, node, thread_index, msm, b0, &next0); + classify_and_dispatch (vm, node, thread_index, msm, b1, &next1); + classify_and_dispatch (vm, node, thread_index, msm, b2, &next2); + classify_and_dispatch (vm, node, thread_index, msm, b3, &next3); /* verify speculative enqueues, maybe switch current next frame */ /* if next0==next1==next_index then nothing special needs to be done */ @@ -393,7 +393,7 @@ l2input_node_inline (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 1); - classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0); + classify_and_dispatch (vm, node, thread_index, msm, b0, &next0); /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, diff --git a/src/vnet/l2/l2_output.c b/src/vnet/l2/l2_output.c index 00f22571..e17b2a16 100644 --- a/src/vnet/l2/l2_output.c +++ b/src/vnet/l2/l2_output.c @@ -643,11 +643,11 @@ l2output_create_output_node_mapping (vlib_main_t * vlib_main, vnet_main_t * vnet hw0 = vnet_get_sup_hw_interface (vnet_main, sw_if_index); - uword cpu_number; + uword thread_index; - cpu_number = os_get_cpu_number (); + thread_index = vlib_get_thread_index (); - if (cpu_number) + if (thread_index) { u32 oldflags; diff --git a/src/vnet/l2tp/decap.c b/src/vnet/l2tp/decap.c index e8986935..46104129 100644 --- a/src/vnet/l2tp/decap.c +++ b/src/vnet/l2tp/decap.c @@ -149,7 +149,7 @@ last_stage (vlib_main_t * vm, vlib_node_runtime_t * node, u32 bi) /* per-mapping byte stats include the ethernet header */ vlib_increment_combined_counter (&lm->counter_main, - os_get_cpu_number (), + vlib_get_thread_index (), counter_index, 1 /* packet_increment */ , vlib_buffer_length_in_chain (vm, b) + sizeof (ethernet_header_t)); diff --git a/src/vnet/l2tp/encap.c b/src/vnet/l2tp/encap.c index ed7a9580..dcdfde4b 100644 --- a/src/vnet/l2tp/encap.c +++ b/src/vnet/l2tp/encap.c @@ -124,7 +124,7 @@ last_stage (vlib_main_t * vm, vlib_node_runtime_t * node, u32 bi) /* per-mapping byte stats include the ethernet header */ vlib_increment_combined_counter (&lm->counter_main, - os_get_cpu_number (), + vlib_get_thread_index (), counter_index, 1 /* packet_increment */ , vlib_buffer_length_in_chain (vm, b)); diff --git a/src/vnet/l2tp/l2tp.c b/src/vnet/l2tp/l2tp.c index cb94d7e7..3dedc447 100644 --- a/src/vnet/l2tp/l2tp.c +++ b/src/vnet/l2tp/l2tp.c @@ -157,7 +157,7 @@ test_counters_command_fn (vlib_main_t * vm, u32 session_index; u32 counter_index; u32 nincr = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); /* *INDENT-OFF* */ pool_foreach (session, lm->sessions, @@ -167,11 +167,11 @@ test_counters_command_fn (vlib_main_t * vm, session_index_to_counter_index (session_index, SESSION_COUNTER_USER_TO_NETWORK); vlib_increment_combined_counter (&lm->counter_main, - cpu_index, + thread_index, counter_index, 1/*pkt*/, 1111 /*bytes*/); vlib_increment_combined_counter (&lm->counter_main, - cpu_index, + thread_index, counter_index+1, 1/*pkt*/, 2222 /*bytes*/); nincr++; diff --git a/src/vnet/lisp-gpe/decap.c b/src/vnet/lisp-gpe/decap.c index d887a95f..68769710 100644 --- a/src/vnet/lisp-gpe/decap.c +++ b/src/vnet/lisp-gpe/decap.c @@ -103,7 +103,7 @@ next_index_to_iface (lisp_gpe_main_t * lgm, u32 next_index) } static_always_inline void -incr_decap_stats (vnet_main_t * vnm, u32 cpu_index, u32 length, +incr_decap_stats (vnet_main_t * vnm, u32 thread_index, u32 length, u32 sw_if_index, u32 * last_sw_if_index, u32 * n_packets, u32 * n_bytes) { @@ -122,7 +122,7 @@ incr_decap_stats (vnet_main_t * vnm, u32 cpu_index, u32 length, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, *last_sw_if_index, + thread_index, *last_sw_if_index, *n_packets, *n_bytes); } *last_sw_if_index = sw_if_index; @@ -150,11 +150,11 @@ static uword lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, u8 is_v4) { - u32 n_left_from, next_index, *from, *to_next, cpu_index; + u32 n_left_from, next_index, *from, *to_next, thread_index; u32 n_bytes = 0, n_packets = 0, last_sw_if_index = ~0, drops = 0; lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - cpu_index = os_get_cpu_number (); + thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -267,7 +267,7 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (si0) { - incr_decap_stats (lgm->vnet_main, cpu_index, + incr_decap_stats (lgm->vnet_main, thread_index, vlib_buffer_length_in_chain (vm, b0), si0[0], &last_sw_if_index, &n_packets, &n_bytes); vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0]; @@ -282,7 +282,7 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (si1) { - incr_decap_stats (lgm->vnet_main, cpu_index, + incr_decap_stats (lgm->vnet_main, thread_index, vlib_buffer_length_in_chain (vm, b1), si1[0], &last_sw_if_index, &n_packets, &n_bytes); vnet_buffer (b1)->sw_if_index[VLIB_RX] = si1[0]; @@ -397,7 +397,7 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (si0) { - incr_decap_stats (lgm->vnet_main, cpu_index, + incr_decap_stats (lgm->vnet_main, thread_index, vlib_buffer_length_in_chain (vm, b0), si0[0], &last_sw_if_index, &n_packets, &n_bytes); vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0]; @@ -430,7 +430,7 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } /* flush iface stats */ - incr_decap_stats (lgm->vnet_main, cpu_index, 0, ~0, &last_sw_if_index, + incr_decap_stats (lgm->vnet_main, thread_index, 0, ~0, &last_sw_if_index, &n_packets, &n_bytes); vlib_node_increment_counter (vm, lisp_gpe_ip4_input_node.index, LISP_GPE_ERROR_NO_TUNNEL, drops); diff --git a/src/vnet/lldp/lldp_input.c b/src/vnet/lldp/lldp_input.c index 762743d0..e88f6fdb 100644 --- a/src/vnet/lldp/lldp_input.c +++ b/src/vnet/lldp/lldp_input.c @@ -35,7 +35,7 @@ typedef struct static void lldp_rpc_update_peer_cb (const lldp_intf_update_t * a) { - ASSERT (os_get_cpu_number () == 0); + ASSERT (vlib_get_thread_index () == 0); lldp_intf_t *n = lldp_get_intf (&lldp_main, a->hw_if_index); if (!n) diff --git a/src/vnet/map/ip4_map.c b/src/vnet/map/ip4_map.c index 1a20d704..e39b6f14 100644 --- a/src/vnet/map/ip4_map.c +++ b/src/vnet/map/ip4_map.c @@ -248,7 +248,7 @@ ip4_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) next_index = node->cached_next_index; map_main_t *mm = &map_main; vlib_combined_counter_main_t *cm = mm->domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -377,7 +377,7 @@ ip4_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) ip40) ? IP4_MAP_NEXT_IP6_REWRITE : next0; vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, map_domain_index0, 1, clib_net_to_host_u16 (ip6h0->payload_length) + @@ -409,7 +409,7 @@ ip4_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) ip41) ? IP4_MAP_NEXT_IP6_REWRITE : next1; vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, map_domain_index1, 1, clib_net_to_host_u16 (ip6h1->payload_length) + @@ -520,7 +520,7 @@ ip4_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) ip40) ? IP4_MAP_NEXT_IP6_REWRITE : next0; vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, map_domain_index0, 1, clib_net_to_host_u16 (ip6h0->payload_length) + @@ -564,7 +564,7 @@ ip4_map_reass (vlib_main_t * vm, next_index = node->cached_next_index; map_main_t *mm = &map_main; vlib_combined_counter_main_t *cm = mm->domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 *fragments_to_drop = NULL; u32 *fragments_to_loopback = NULL; @@ -694,8 +694,8 @@ ip4_map_reass (vlib_main_t * vm, { if (error0 == MAP_ERROR_NONE) vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, map_domain_index0, - 1, + thread_index, + map_domain_index0, 1, clib_net_to_host_u16 (ip60->payload_length) + 40); next0 = diff --git a/src/vnet/map/ip4_map_t.c b/src/vnet/map/ip4_map_t.c index b63d76bf..5f2bcbf9 100644 --- a/src/vnet/map/ip4_map_t.c +++ b/src/vnet/map/ip4_map_t.c @@ -477,7 +477,7 @@ ip4_map_t_icmp (vlib_main_t * vm, n_left_from = frame->n_vectors; next_index = node->cached_next_index; vlib_combined_counter_main_t *cm = map_main.domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -520,7 +520,7 @@ ip4_map_t_icmp (vlib_main_t * vm, if (PREDICT_TRUE (error0 == MAP_ERROR_NONE)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, vnet_buffer (p0)->map_t. map_domain_index, 1, len0); } @@ -1051,7 +1051,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) n_left_from = frame->n_vectors; next_index = node->cached_next_index; vlib_combined_counter_main_t *cm = map_main.domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -1158,7 +1158,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error0 == MAP_ERROR_NONE && next0 != IP4_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, vnet_buffer (p0)->map_t. map_domain_index, 1, clib_net_to_host_u16 (ip40-> @@ -1169,7 +1169,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error1 == MAP_ERROR_NONE && next1 != IP4_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, vnet_buffer (p1)->map_t. map_domain_index, 1, clib_net_to_host_u16 (ip41-> @@ -1252,7 +1252,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error0 == MAP_ERROR_NONE && next0 != IP4_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_TX, - cpu_index, + thread_index, vnet_buffer (p0)->map_t. map_domain_index, 1, clib_net_to_host_u16 (ip40-> diff --git a/src/vnet/map/ip6_map.c b/src/vnet/map/ip6_map.c index f7eb768f..63ada962 100644 --- a/src/vnet/map/ip6_map.c +++ b/src/vnet/map/ip6_map.c @@ -172,7 +172,7 @@ ip6_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vlib_node_get_runtime (vm, ip6_map_node.index); map_main_t *mm = &map_main; vlib_combined_counter_main_t *cm = mm->domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -319,7 +319,7 @@ ip6_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) IP6_MAP_NEXT_IP4_REWRITE : next0; } vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, map_domain_index0, 1, clib_net_to_host_u16 (ip40->length)); @@ -352,7 +352,7 @@ ip6_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) IP6_MAP_NEXT_IP4_REWRITE : next1; } vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, map_domain_index1, 1, clib_net_to_host_u16 (ip41->length)); @@ -505,7 +505,7 @@ ip6_map (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) IP6_MAP_NEXT_IP4_REWRITE : next0; } vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, map_domain_index0, 1, clib_net_to_host_u16 (ip40->length)); @@ -820,7 +820,7 @@ ip6_map_ip4_reass (vlib_main_t * vm, vlib_node_get_runtime (vm, ip6_map_ip4_reass_node.index); map_main_t *mm = &map_main; vlib_combined_counter_main_t *cm = mm->domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 *fragments_to_drop = NULL; u32 *fragments_to_loopback = NULL; @@ -958,8 +958,8 @@ ip6_map_ip4_reass (vlib_main_t * vm, { if (error0 == MAP_ERROR_NONE) vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, map_domain_index0, - 1, + thread_index, + map_domain_index0, 1, clib_net_to_host_u16 (ip40->length)); next0 = @@ -1015,7 +1015,7 @@ ip6_map_icmp_relay (vlib_main_t * vm, vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, ip6_map_icmp_relay_node.index); map_main_t *mm = &map_main; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u16 *fragment_ids, *fid; from = vlib_frame_vector_args (frame); @@ -1143,7 +1143,8 @@ ip6_map_icmp_relay (vlib_main_t * vm, ip_csum_t sum = ip_incremental_checksum (0, new_icmp40, nlen - 20); new_icmp40->checksum = ~ip_csum_fold (sum); - vlib_increment_simple_counter (&mm->icmp_relayed, cpu_index, 0, 1); + vlib_increment_simple_counter (&mm->icmp_relayed, thread_index, 0, + 1); error: if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED)) diff --git a/src/vnet/map/ip6_map_t.c b/src/vnet/map/ip6_map_t.c index eb3996c2..99151678 100644 --- a/src/vnet/map/ip6_map_t.c +++ b/src/vnet/map/ip6_map_t.c @@ -448,7 +448,7 @@ ip6_map_t_icmp (vlib_main_t * vm, n_left_from = frame->n_vectors; next_index = node->cached_next_index; vlib_combined_counter_main_t *cm = map_main.domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -493,7 +493,7 @@ ip6_map_t_icmp (vlib_main_t * vm, if (PREDICT_TRUE (error0 == MAP_ERROR_NONE)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, vnet_buffer (p0)-> map_t.map_domain_index, 1, len0); @@ -1051,7 +1051,7 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, ip6_map_t_node.index); vlib_combined_counter_main_t *cm = map_main.domain_counters; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -1218,7 +1218,7 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error0 == MAP_ERROR_NONE && next0 != IP6_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, vnet_buffer (p0)-> map_t.map_domain_index, 1, clib_net_to_host_u16 @@ -1229,7 +1229,7 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error1 == MAP_ERROR_NONE && next1 != IP6_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, vnet_buffer (p1)-> map_t.map_domain_index, 1, clib_net_to_host_u16 @@ -1403,7 +1403,7 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (error0 == MAP_ERROR_NONE && next0 != IP6_MAPT_NEXT_MAPT_ICMP)) { vlib_increment_combined_counter (cm + MAP_DOMAIN_COUNTER_RX, - cpu_index, + thread_index, vnet_buffer (p0)-> map_t.map_domain_index, 1, clib_net_to_host_u16 diff --git a/src/vnet/mpls/mpls_input.c b/src/vnet/mpls/mpls_input.c index 893c4511..1b9bdd05 100644 --- a/src/vnet/mpls/mpls_input.c +++ b/src/vnet/mpls/mpls_input.c @@ -76,7 +76,7 @@ mpls_input_inline (vlib_main_t * vm, u32 n_left_from, next_index, * from, * to_next; mpls_input_runtime_t * rt; mpls_main_t * mm; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); vlib_simple_counter_main_t * cm; vnet_main_t * vnm = vnet_get_main(); @@ -151,7 +151,7 @@ mpls_input_inline (vlib_main_t * vm, next0 = MPLS_INPUT_NEXT_LOOKUP; vnet_feature_arc_start(mm->input_feature_arc_index, sw_if_index0, &next0, b0); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); } if (PREDICT_FALSE(h1[3] == 0)) @@ -164,7 +164,7 @@ mpls_input_inline (vlib_main_t * vm, next1 = MPLS_INPUT_NEXT_LOOKUP; vnet_feature_arc_start(mm->input_feature_arc_index, sw_if_index1, &next1, b1); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1); } if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -215,7 +215,7 @@ mpls_input_inline (vlib_main_t * vm, { next0 = MPLS_INPUT_NEXT_LOOKUP; vnet_feature_arc_start(mm->input_feature_arc_index, sw_if_index0, &next0, b0); - vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); + vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1); } if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) diff --git a/src/vnet/mpls/mpls_lookup.c b/src/vnet/mpls/mpls_lookup.c index 475bb204..ace6a70f 100644 --- a/src/vnet/mpls/mpls_lookup.c +++ b/src/vnet/mpls/mpls_lookup.c @@ -67,7 +67,7 @@ mpls_lookup (vlib_main_t * vm, vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters; u32 n_left_from, next_index, * from, * to_next; mpls_main_t * mm = &mpls_main; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -220,16 +220,16 @@ mpls_lookup (vlib_main_t * vm, vnet_buffer (b3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, b1)); vlib_increment_combined_counter - (cm, cpu_index, lbi2, 1, + (cm, thread_index, lbi2, 1, vlib_buffer_length_in_chain (vm, b2)); vlib_increment_combined_counter - (cm, cpu_index, lbi3, 1, + (cm, thread_index, lbi3, 1, vlib_buffer_length_in_chain (vm, b3)); /* @@ -351,7 +351,7 @@ mpls_lookup (vlib_main_t * vm, vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); /* @@ -440,7 +440,7 @@ mpls_load_balance (vlib_main_t * vm, { vlib_combined_counter_main_t * cm = &load_balance_main.lbm_via_counters; u32 n_left_from, n_left_to_next, * from, * to_next; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u32 next; from = vlib_frame_vector_args (frame); @@ -536,10 +536,10 @@ mpls_load_balance (vlib_main_t * vm, vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) @@ -597,7 +597,7 @@ mpls_load_balance (vlib_main_t * vm, vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_validate_buffer_enqueue_x1 (vm, node, next, diff --git a/src/vnet/mpls/mpls_output.c b/src/vnet/mpls/mpls_output.c index 08018fd1..d90dec21 100644 --- a/src/vnet/mpls/mpls_output.c +++ b/src/vnet/mpls/mpls_output.c @@ -64,12 +64,12 @@ mpls_output_inline (vlib_main_t * vm, vlib_frame_t * from_frame, int is_midchain) { - u32 n_left_from, next_index, * from, * to_next, cpu_index; + u32 n_left_from, next_index, * from, * to_next, thread_index; vlib_node_runtime_t * error_node; u32 n_left_to_next; mpls_main_t *mm; - cpu_index = os_get_cpu_number(); + thread_index = vlib_get_thread_index(); error_node = vlib_node_get_runtime (vm, mpls_output_node.index); from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -137,13 +137,13 @@ mpls_output_inline (vlib_main_t * vm, /* Bump the adj counters for packet and bytes */ vlib_increment_combined_counter (&adjacency_counters, - cpu_index, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); vlib_increment_combined_counter (&adjacency_counters, - cpu_index, + thread_index, adj_index1, 1, vlib_buffer_length_in_chain (vm, p1) + rw_len1); @@ -245,7 +245,7 @@ mpls_output_inline (vlib_main_t * vm, vlib_increment_combined_counter (&adjacency_counters, - cpu_index, + thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0); diff --git a/src/vnet/pg/input.c b/src/vnet/pg/input.c index 2649798b..597ae060 100644 --- a/src/vnet/pg/input.c +++ b/src/vnet/pg/input.c @@ -893,7 +893,7 @@ pg_generate_set_lengths (pg_main_t * pg, vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number (), + vlib_get_thread_index (), si->sw_if_index, n_buffers, length_sum); } @@ -1266,7 +1266,7 @@ pg_stream_fill_helper (pg_main_t * pg, l += vlib_buffer_index_length_in_chain (vm, buffers[i]); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number (), + vlib_get_thread_index (), si->sw_if_index, n_alloc, l); s->current_replay_packet_index += n_alloc; s->current_replay_packet_index %= diff --git a/src/vnet/replication.c b/src/vnet/replication.c index 86d922b5..233a8c2f 100644 --- a/src/vnet/replication.c +++ b/src/vnet/replication.c @@ -31,16 +31,16 @@ replication_prep (vlib_main_t * vm, { replication_main_t *rm = &replication_main; replication_context_t *ctx; - uword cpu_number = vm->cpu_index; + uword thread_index = vm->thread_index; ip4_header_t *ip; u32 ctx_id; /* Allocate a context, reserve context 0 */ - if (PREDICT_FALSE (rm->contexts[cpu_number] == 0)) - pool_get_aligned (rm->contexts[cpu_number], ctx, CLIB_CACHE_LINE_BYTES); + if (PREDICT_FALSE (rm->contexts[thread_index] == 0)) + pool_get_aligned (rm->contexts[thread_index], ctx, CLIB_CACHE_LINE_BYTES); - pool_get_aligned (rm->contexts[cpu_number], ctx, CLIB_CACHE_LINE_BYTES); - ctx_id = ctx - rm->contexts[cpu_number]; + pool_get_aligned (rm->contexts[thread_index], ctx, CLIB_CACHE_LINE_BYTES); + ctx_id = ctx - rm->contexts[thread_index]; /* Save state from vlib buffer */ ctx->saved_free_list_index = b0->free_list_index; @@ -94,11 +94,11 @@ replication_recycle (vlib_main_t * vm, vlib_buffer_t * b0, u32 is_last) { replication_main_t *rm = &replication_main; replication_context_t *ctx; - uword cpu_number = vm->cpu_index; + uword thread_index = vm->thread_index; ip4_header_t *ip; /* Get access to the replication context */ - ctx = pool_elt_at_index (rm->contexts[cpu_number], b0->recycle_count); + ctx = pool_elt_at_index (rm->contexts[thread_index], b0->recycle_count); /* Restore vnet buffer state */ clib_memcpy (vnet_buffer (b0), ctx->vnet_buffer, @@ -133,7 +133,7 @@ replication_recycle (vlib_main_t * vm, vlib_buffer_t * b0, u32 is_last) b0->flags &= ~VLIB_BUFFER_RECYCLE; /* Free context back to its pool */ - pool_put (rm->contexts[cpu_number], ctx); + pool_put (rm->contexts[thread_index], ctx); } return ctx; @@ -160,7 +160,7 @@ replication_recycle_callback (vlib_main_t * vm, vlib_buffer_free_list_t * fl) replication_main_t *rm = &replication_main; replication_context_t *ctx; u32 feature_node_index = 0; - uword cpu_number = vm->cpu_index; + uword thread_index = vm->thread_index; /* * All buffers in the list are destined to the same recycle node. @@ -172,7 +172,7 @@ replication_recycle_callback (vlib_main_t * vm, vlib_buffer_free_list_t * fl) { bi0 = fl->buffers[0]; b0 = vlib_get_buffer (vm, bi0); - ctx = pool_elt_at_index (rm->contexts[cpu_number], b0->recycle_count); + ctx = pool_elt_at_index (rm->contexts[thread_index], b0->recycle_count); feature_node_index = ctx->recycle_node_index; } diff --git a/src/vnet/replication.h b/src/vnet/replication.h index 5dc554c9..ce4b3ff1 100644 --- a/src/vnet/replication.h +++ b/src/vnet/replication.h @@ -100,7 +100,7 @@ replication_get_ctx (vlib_buffer_t * b0) replication_main_t *rm = &replication_main; return replication_is_recycled (b0) ? - pool_elt_at_index (rm->contexts[os_get_cpu_number ()], + pool_elt_at_index (rm->contexts[vlib_get_thread_index ()], b0->recycle_count) : 0; } diff --git a/src/vnet/session/node.c b/src/vnet/session/node.c index b86e87d9..dd211c51 100644 --- a/src/vnet/session/node.c +++ b/src/vnet/session/node.c @@ -311,7 +311,7 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, unix_shared_memory_queue_t *q; application_t *app; int n_tx_packets = 0; - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; int i, rv; f64 now = vlib_time_now (vm); diff --git a/src/vnet/sr/sr_localsid.c b/src/vnet/sr/sr_localsid.c index 2e3d56de..6d72a506 100755 --- a/src/vnet/sr/sr_localsid.c +++ b/src/vnet/sr/sr_localsid.c @@ -887,7 +887,7 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -974,26 +974,26 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (((next0 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls0 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b0)); + &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter (((next1 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls1 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b1)); + &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b1)); vlib_increment_combined_counter (((next2 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls2 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b2)); + &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b2)); vlib_increment_combined_counter (((next3 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls3 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b3)); + &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b3)); vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, @@ -1062,8 +1062,8 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (((next0 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls0 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b0)); + &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b0)); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); @@ -1103,7 +1103,7 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); while (n_left_from > 0) { @@ -1205,26 +1205,26 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (((next0 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls0 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b0)); + &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b0)); vlib_increment_combined_counter (((next1 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls1 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b1)); + &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b1)); vlib_increment_combined_counter (((next2 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls2 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b2)); + &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b2)); vlib_increment_combined_counter (((next3 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls3 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b3)); + &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b3)); vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, @@ -1295,8 +1295,8 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_increment_combined_counter (((next0 == SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : - &(sm->sr_ls_valid_counters)), cpu_index, ls0 - sm->localsids, 1, - vlib_buffer_length_in_chain (vm, b0)); + &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids, + 1, vlib_buffer_length_in_chain (vm, b0)); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); diff --git a/src/vnet/tcp/builtin_client.c b/src/vnet/tcp/builtin_client.c index e3705060..c1567aa0 100644 --- a/src/vnet/tcp/builtin_client.c +++ b/src/vnet/tcp/builtin_client.c @@ -174,7 +174,7 @@ tclient_thread_fn (void *arg) pthread_sigmask (SIG_SETMASK, &s, 0); } - clib_per_cpu_mheaps[os_get_cpu_number ()] = clib_per_cpu_mheaps[0]; + clib_per_cpu_mheaps[vlib_get_thread_index ()] = clib_per_cpu_mheaps[0]; while (1) { diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index b2a371e2..b6c34828 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -646,10 +646,10 @@ const static transport_proto_vft_t tcp6_proto = { void tcp_timer_keep_handler (u32 conn_index) { - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); tcp_connection_t *tc; - tc = tcp_connection_get (conn_index, cpu_index); + tc = tcp_connection_get (conn_index, thread_index); tc->timers[TCP_TIMER_KEEP] = TCP_TIMER_HANDLE_INVALID; tcp_connection_close (tc); @@ -675,10 +675,10 @@ tcp_timer_establish_handler (u32 conn_index) void tcp_timer_waitclose_handler (u32 conn_index) { - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); tcp_connection_t *tc; - tc = tcp_connection_get (conn_index, cpu_index); + tc = tcp_connection_get (conn_index, thread_index); tc->timers[TCP_TIMER_WAITCLOSE] = TCP_TIMER_HANDLE_INVALID; /* Session didn't come back with a close(). Send FIN either way diff --git a/src/vnet/tcp/tcp_debug.h b/src/vnet/tcp/tcp_debug.h index 0090e15e..eaca672c 100644 --- a/src/vnet/tcp/tcp_debug.h +++ b/src/vnet/tcp/tcp_debug.h @@ -343,7 +343,7 @@ typedef enum _tcp_dbg_evt } \ else \ { \ - u32 _thread_index = os_get_cpu_number (); \ + u32 _thread_index = vlib_get_thread_index (); \ _tc = tcp_connection_get (_tc_index, _thread_index); \ } \ ELOG_TYPE_DECLARE (_e) = \ diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index a8224dc2..7e9fa47b 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1142,7 +1142,7 @@ tcp46_established_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, int is_ip4) { u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index, errors = 0; + u32 my_thread_index = vm->thread_index, errors = 0; tcp_main_t *tm = vnet_get_tcp_main (); from = vlib_frame_vector_args (from_frame); @@ -1332,7 +1332,7 @@ tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { tcp_main_t *tm = vnet_get_tcp_main (); u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index, errors = 0; + u32 my_thread_index = vm->thread_index, errors = 0; u8 sst = is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP; from = vlib_frame_vector_args (from_frame); @@ -1634,7 +1634,7 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { tcp_main_t *tm = vnet_get_tcp_main (); u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index, errors = 0; + u32 my_thread_index = vm->thread_index, errors = 0; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -1989,7 +1989,7 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, int is_ip4) { u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; tcp_main_t *tm = vnet_get_tcp_main (); u8 sst = is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP; @@ -2243,7 +2243,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, int is_ip4) { u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; tcp_main_t *tm = vnet_get_tcp_main (); from = vlib_frame_vector_args (from_frame); diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index ea157bd7..e18bfad7 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -387,8 +387,8 @@ tcp_make_options (tcp_connection_t * tc, tcp_options_t * opts, #define tcp_get_free_buffer_index(tm, bidx) \ do { \ u32 *my_tx_buffers, n_free_buffers; \ - u32 cpu_index = os_get_cpu_number(); \ - my_tx_buffers = tm->tx_buffers[cpu_index]; \ + u32 thread_index = vlib_get_thread_index(); \ + my_tx_buffers = tm->tx_buffers[thread_index]; \ if (PREDICT_FALSE(vec_len (my_tx_buffers) == 0)) \ { \ n_free_buffers = 32; /* TODO config or macro */ \ @@ -396,7 +396,7 @@ do { \ _vec_len(my_tx_buffers) = vlib_buffer_alloc_from_free_list ( \ tm->vlib_main, my_tx_buffers, n_free_buffers, \ VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); \ - tm->tx_buffers[cpu_index] = my_tx_buffers; \ + tm->tx_buffers[thread_index] = my_tx_buffers; \ } \ /* buffer shortage */ \ if (PREDICT_FALSE (vec_len (my_tx_buffers) == 0)) \ @@ -408,8 +408,8 @@ do { \ #define tcp_return_buffer(tm) \ do { \ u32 *my_tx_buffers; \ - u32 cpu_index = os_get_cpu_number(); \ - my_tx_buffers = tm->tx_buffers[cpu_index]; \ + u32 thread_index = vlib_get_thread_index(); \ + my_tx_buffers = tm->tx_buffers[thread_index]; \ _vec_len (my_tx_buffers) +=1; \ } while (0) @@ -942,7 +942,7 @@ tcp_send_ack (tcp_connection_t * tc) void tcp_timer_delack_handler (u32 index) { - u32 thread_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); tcp_connection_t *tc; tc = tcp_connection_get (index, thread_index); @@ -1022,7 +1022,7 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn) { tcp_main_t *tm = vnet_get_tcp_main (); vlib_main_t *vm = vlib_get_main (); - u32 thread_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); tcp_connection_t *tc; vlib_buffer_t *b; u32 bi, snd_space, n_bytes; @@ -1152,7 +1152,7 @@ tcp_timer_persist_handler (u32 index) { tcp_main_t *tm = vnet_get_tcp_main (); vlib_main_t *vm = vlib_get_main (); - u32 thread_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); tcp_connection_t *tc; vlib_buffer_t *b; u32 bi, n_bytes; @@ -1313,7 +1313,7 @@ tcp46_output_inline (vlib_main_t * vm, vlib_frame_t * from_frame, int is_ip4) { u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -1524,7 +1524,7 @@ tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, u8 is_ip4) { u32 n_left_from, next_index, *from, *to_next; - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; diff --git a/src/vnet/udp/udp_input.c b/src/vnet/udp/udp_input.c index 4b22109b..810278e6 100644 --- a/src/vnet/udp/udp_input.c +++ b/src/vnet/udp/udp_input.c @@ -70,7 +70,7 @@ udp4_uri_input_node_fn (vlib_main_t * vm, udp4_uri_input_next_t next_index; udp_uri_main_t *um = vnet_get_udp_main (); session_manager_main_t *smm = vnet_get_session_manager_main (); - u32 my_thread_index = vm->cpu_index; + u32 my_thread_index = vm->thread_index; u8 my_enqueue_epoch; u32 *session_indices_to_enqueue; static u32 serial_number; diff --git a/src/vnet/unix/tapcli.c b/src/vnet/unix/tapcli.c index fb1a8bac..0fc62f6c 100644 --- a/src/vnet/unix/tapcli.c +++ b/src/vnet/unix/tapcli.c @@ -366,7 +366,7 @@ static uword tapcli_rx_iface(vlib_main_t * vm, vlib_increment_combined_counter ( vnet_main.interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number(), ti->sw_if_index, + vlib_get_thread_index(), ti->sw_if_index, 1, n_bytes_in_packet); if (PREDICT_FALSE(n_trace > 0)) { diff --git a/src/vnet/unix/tuntap.c b/src/vnet/unix/tuntap.c index 2cfcc92f..ac674653 100644 --- a/src/vnet/unix/tuntap.c +++ b/src/vnet/unix/tuntap.c @@ -189,7 +189,7 @@ tuntap_tx (vlib_main_t * vm, /* Update tuntap interface output stats. */ vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - vm->cpu_index, + vm->thread_index, tm->sw_if_index, n_packets, n_bytes); @@ -297,7 +297,7 @@ tuntap_rx (vlib_main_t * vm, vlib_increment_combined_counter (vnet_main.interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number(), + vlib_get_thread_index(), tm->sw_if_index, 1, n_bytes_in_packet); diff --git a/src/vnet/vxlan-gpe/decap.c b/src/vnet/vxlan-gpe/decap.c index 22ab4b62..d4fe4231 100644 --- a/src/vnet/vxlan-gpe/decap.c +++ b/src/vnet/vxlan-gpe/decap.c @@ -115,7 +115,7 @@ vxlan_gpe_input (vlib_main_t * vm, vxlan4_gpe_tunnel_key_t last_key4; vxlan6_gpe_tunnel_key_t last_key6; u32 pkts_decapsulated = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; if (is_ip4) @@ -342,7 +342,7 @@ vxlan_gpe_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; stats_sw_if_index = sw_if_index0; @@ -427,7 +427,7 @@ vxlan_gpe_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len1; stats_sw_if_index = sw_if_index1; @@ -588,7 +588,7 @@ vxlan_gpe_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; stats_sw_if_index = sw_if_index0; @@ -615,7 +615,7 @@ vxlan_gpe_input (vlib_main_t * vm, if (stats_n_packets) { vlib_increment_combined_counter ( - im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, cpu_index, + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } diff --git a/src/vnet/vxlan-gpe/encap.c b/src/vnet/vxlan-gpe/encap.c index 3a486e56..67ed94b4 100644 --- a/src/vnet/vxlan-gpe/encap.c +++ b/src/vnet/vxlan-gpe/encap.c @@ -151,7 +151,7 @@ vxlan_gpe_encap (vlib_main_t * vm, vnet_main_t * vnm = ngm->vnet_main; vnet_interface_main_t * im = &vnm->interface_main; u32 pkts_encapsulated = 0; - u32 cpu_index = os_get_cpu_number (); + u32 thread_index = vlib_get_thread_index (); u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; from = vlib_frame_vector_args (from_frame); @@ -253,7 +253,7 @@ vxlan_gpe_encap (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_sw_if_index = sw_if_index0; stats_n_packets = 2; stats_n_bytes = len0 + len1; @@ -262,10 +262,10 @@ vxlan_gpe_encap (vlib_main_t * vm, { vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, sw_if_index0, 1, len0); + thread_index, sw_if_index0, 1, len0); vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, sw_if_index1, 1, len1); + thread_index, sw_if_index1, 1, len1); } } @@ -335,7 +335,7 @@ vxlan_gpe_encap (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter ( im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; stats_sw_if_index = sw_if_index0; @@ -359,7 +359,7 @@ vxlan_gpe_encap (vlib_main_t * vm, if (stats_n_packets) { vlib_increment_combined_counter ( - im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } diff --git a/src/vnet/vxlan/decap.c b/src/vnet/vxlan/decap.c index 514b2c99..2acb1f6f 100644 --- a/src/vnet/vxlan/decap.c +++ b/src/vnet/vxlan/decap.c @@ -81,7 +81,7 @@ vxlan_input (vlib_main_t * vm, vxlan4_tunnel_key_t last_key4; vxlan6_tunnel_key_t last_key6; u32 pkts_decapsulated = 0; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; if (is_ip4) @@ -314,7 +314,7 @@ vxlan_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; @@ -468,7 +468,7 @@ vxlan_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len1; @@ -674,7 +674,7 @@ vxlan_input (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; @@ -711,7 +711,7 @@ vxlan_input (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } diff --git a/src/vnet/vxlan/encap.c b/src/vnet/vxlan/encap.c index 5b63064a..4cfbbc23 100644 --- a/src/vnet/vxlan/encap.c +++ b/src/vnet/vxlan/encap.c @@ -77,7 +77,7 @@ vxlan_encap_inline (vlib_main_t * vm, vnet_interface_main_t * im = &vnm->interface_main; u32 pkts_encapsulated = 0; u16 old_l0 = 0, old_l1 = 0; - u32 cpu_index = os_get_cpu_number(); + u32 thread_index = vlib_get_thread_index(); u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; u32 sw_if_index0 = 0, sw_if_index1 = 0; u32 next0 = 0, next1 = 0; @@ -301,7 +301,7 @@ vxlan_encap_inline (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, stats_sw_if_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_sw_if_index = sw_if_index0; stats_n_packets = 2; @@ -311,10 +311,10 @@ vxlan_encap_inline (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, sw_if_index0, 1, len0); + thread_index, sw_if_index0, 1, len0); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, sw_if_index1, 1, len1); + thread_index, sw_if_index1, 1, len1); } } @@ -464,7 +464,7 @@ vxlan_encap_inline (vlib_main_t * vm, if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, stats_sw_if_index, + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; @@ -496,7 +496,7 @@ vxlan_encap_inline (vlib_main_t * vm, { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } diff --git a/src/vpp/stats/stats.c b/src/vpp/stats/stats.c index 042d02e2..4309cd51 100644 --- a/src/vpp/stats/stats.c +++ b/src/vpp/stats/stats.c @@ -66,14 +66,14 @@ _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) void dslock (stats_main_t * sm, int release_hint, int tag) { - u32 thread_id; + u32 thread_index; data_structure_lock_t *l = sm->data_structure_lock; if (PREDICT_FALSE (l == 0)) return; - thread_id = os_get_cpu_number (); - if (l->lock && l->thread_id == thread_id) + thread_index = vlib_get_thread_index (); + if (l->lock && l->thread_index == thread_index) { l->count++; return; @@ -85,7 +85,7 @@ dslock (stats_main_t * sm, int release_hint, int tag) while (__sync_lock_test_and_set (&l->lock, 1)) /* zzzz */ ; l->tag = tag; - l->thread_id = thread_id; + l->thread_index = thread_index; l->count = 1; } @@ -99,14 +99,14 @@ stats_dslock_with_hint (int hint, int tag) void dsunlock (stats_main_t * sm) { - u32 thread_id; + u32 thread_index; data_structure_lock_t *l = sm->data_structure_lock; if (PREDICT_FALSE (l == 0)) return; - thread_id = os_get_cpu_number (); - ASSERT (l->lock && l->thread_id == thread_id); + thread_index = vlib_get_thread_index (); + ASSERT (l->lock && l->thread_index == thread_index); l->count--; if (l->count == 0) { diff --git a/src/vpp/stats/stats.h b/src/vpp/stats/stats.h index 118115be..024dc78e 100644 --- a/src/vpp/stats/stats.h +++ b/src/vpp/stats/stats.h @@ -30,7 +30,7 @@ typedef struct { volatile u32 lock; volatile u32 release_hint; - u32 thread_id; + u32 thread_index; u32 count; int tag; } data_structure_lock_t; -- cgit 1.2.3-korg From a0558307187ef2317f31e3e876a1a5e1faa2541c Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 13 Apr 2017 00:44:52 -0700 Subject: Remove unsed parameter from fib_table_entry_special_add() (only used in FIB tests). The DPO was incorrectly initialised with FIB_PROTO_MAX Change-Id: I962df9e162e4dfb6837a5ce79ea795d5ff2d7315 Signed-off-by: Neale Ranns --- src/plugins/ila/ila.c | 3 +-- src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c | 4 +--- src/plugins/lb/lb.c | 3 +-- src/vnet/dhcp/client.c | 3 +-- src/vnet/dhcp/dhcp4_proxy_node.c | 3 +-- src/vnet/fib/fib_bfd.c | 3 +-- src/vnet/fib/fib_path.c | 3 +-- src/vnet/fib/fib_table.c | 15 ++------------- src/vnet/fib/fib_table.h | 14 ++++++-------- src/vnet/fib/fib_test.c | 16 ++++++++-------- src/vnet/fib/ip4_fib.c | 3 +-- src/vnet/fib/ip6_fib.c | 6 ++---- src/vnet/gre/interface.c | 3 +-- src/vnet/ip/ip4_forward.c | 6 ++---- src/vnet/ip/ip4_source_check.c | 2 +- src/vnet/lisp-gpe/lisp_gpe_tunnel.c | 3 +-- src/vnet/map/map.c | 4 +--- src/vnet/vxlan/vxlan.c | 2 +- 18 files changed, 33 insertions(+), 63 deletions(-) (limited to 'src/vnet/gre') diff --git a/src/plugins/ila/ila.c b/src/plugins/ila/ila.c index edbf3017..fd56043e 100644 --- a/src/plugins/ila/ila.c +++ b/src/plugins/ila/ila.c @@ -736,8 +736,7 @@ ila_add_del_entry (ila_add_del_entry_args_t * args) fib_table_entry_special_add(0, &next_hop, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); e->next_hop_child_index = fib_entry_child_add(e->next_hop_fib_entry_index, ila_fib_node_type, diff --git a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c index 88d7d205..cfc550cd 100644 --- a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c +++ b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c @@ -336,9 +336,7 @@ vxlan_gpe_enable_disable_ioam_for_dest (vlib_main_t * vm, t1->fib_entry_index = fib_table_entry_special_add (outer_fib_index, &tun_dst_pfx, - FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE); t1->sibling_index = fib_entry_child_add (t1->fib_entry_index, hm->fib_entry_type, t1 - hm->dst_tunnels); diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index addc2a42..cc3f8532 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -510,8 +510,7 @@ next: fib_table_entry_special_add(0, &nh, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); as->next_hop_child_index = fib_entry_child_add(as->next_hop_fib_entry_index, lbm->fib_node_type, diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c index 29749a33..7c3f7f6a 100644 --- a/src/vnet/dhcp/client.c +++ b/src/vnet/dhcp/client.c @@ -781,8 +781,7 @@ int dhcp_client_add_del (dhcp_client_add_del_args_t * a) c->sw_if_index), &all_1s, FIB_SOURCE_DHCP, - FIB_ENTRY_FLAG_LOCAL, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOCAL); /* * enable the interface to RX IPv4 packets diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c index 1c84881a..26e1e65c 100644 --- a/src/vnet/dhcp/dhcp4_proxy_node.c +++ b/src/vnet/dhcp/dhcp4_proxy_node.c @@ -807,8 +807,7 @@ dhcp4_proxy_set_server (ip46_address_t *addr, fib_table_entry_special_add(rx_fib_index, &all_1s, FIB_SOURCE_DHCP, - FIB_ENTRY_FLAG_LOCAL, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOCAL); fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4); } } diff --git a/src/vnet/fib/fib_bfd.c b/src/vnet/fib/fib_bfd.c index e5affb8d..734ee8cc 100644 --- a/src/vnet/fib/fib_bfd.c +++ b/src/vnet/fib/fib_bfd.c @@ -109,8 +109,7 @@ fib_bfd_notify (bfd_listen_event_e event, fei = fib_table_entry_special_add(key->fib_index, &pfx, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); fib_entry_lock(fei); fed = fib_entry_delegate_find_or_add(fib_entry_get(fei), diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index cd7d9278..70c87905 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -1621,8 +1621,7 @@ fib_path_resolve (fib_node_index_t path_index) fei = fib_table_entry_special_add(path->recursive.fp_tbl_id, &pfx, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); path = fib_path_get(path_index); path->fp_via_fib = fei; diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c index b31f35e3..0938ce9b 100644 --- a/src/vnet/fib/fib_table.c +++ b/src/vnet/fib/fib_table.c @@ -371,23 +371,12 @@ fib_node_index_t fib_table_entry_special_add (u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, - fib_entry_flag_t flags, - adj_index_t adj_index) + fib_entry_flag_t flags) { fib_node_index_t fib_entry_index; dpo_id_t tmp_dpo = DPO_INVALID; - if (ADJ_INDEX_INVALID != adj_index) - { - dpo_set(&tmp_dpo, - DPO_ADJACENCY, - FIB_PROTOCOL_MAX, - adj_index); - } - else - { - dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto))); - } + dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto))); fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source, flags, &tmp_dpo); diff --git a/src/vnet/fib/fib_table.h b/src/vnet/fib/fib_table.h index b310aea6..f24d28b7 100644 --- a/src/vnet/fib/fib_table.h +++ b/src/vnet/fib/fib_table.h @@ -126,14 +126,16 @@ extern fib_node_index_t fib_table_get_less_specific(u32 fib_index, /** * @brief - * Add a 'special' entry to the FIB that links to the adj passed + * Add a 'special' entry to the FIB. * A special entry is an entry that the FIB is not expect to resolve * via the usual mechanisms (i.e. recurisve or neighbour adj DB lookup). - * Instead the client/source provides the adj to link to. + * Instead the will link to a DPO valid for the source and/or the flags. * This add is reference counting per-source. So n 'removes' are required * for n 'adds', if the entry is no longer required. + * If the source needs to provide non-default forwarding use: + * fib_table_entry_special_dpo_add() * - * @param fib_index + * @param fib_index * The index of the FIB * * @param prefix @@ -145,17 +147,13 @@ extern fib_node_index_t fib_table_get_less_specific(u32 fib_index, * @param flags * Flags for the entry. * - * @param adj_index - * The adjacency to link to. - * * @return * the index of the fib_entry_t that is created (or exists already). */ extern fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, - fib_entry_flag_t flags, - adj_index_t adj_index); + fib_entry_flag_t flags); /** * @brief diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index e4a8a70e..c58dc5a1 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -1378,8 +1378,8 @@ fib_test_v4 (void) fib_entry_pool_size()); /* - * An EXCLUSIVE route; one where the user (me) provides the exclusive - * adjacency through which the route will resovle + * An special route; one where the user (me) provides the + * adjacency through which the route will resovle by setting the flags */ fib_prefix_t ex_pfx = { .fp_len = 32, @@ -1393,11 +1393,12 @@ fib_test_v4 (void) fib_table_entry_special_add(fib_index, &ex_pfx, FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_EXCLUSIVE, - locked_ai); + FIB_ENTRY_FLAG_LOCAL); fei = fib_table_lookup_exact_match(fib_index, &ex_pfx); - FIB_TEST((ai == fib_entry_get_adj(fei)), - "Exclusive route links to user adj"); + dpo = fib_entry_contribute_ip_forwarding(fei); + dpo = load_balance_get_bucket(dpo->dpoi_index, 0); + FIB_TEST((DPO_RECEIVE == dpo->dpoi_type), + "local interface adj is local"); fib_table_entry_special_remove(fib_index, &ex_pfx, @@ -3675,8 +3676,7 @@ fib_test_v4 (void) fei = fib_table_entry_special_add(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT, - FIB_ENTRY_FLAG_DROP, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_DROP); dpo = fib_entry_contribute_ip_forwarding(fei); FIB_TEST(load_balance_is_drop(dpo), "uRPF exempt 4.1.1.1/32 DROP"); diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c index b03186e8..8e92d851 100644 --- a/src/vnet/fib/ip4_fib.c +++ b/src/vnet/fib/ip4_fib.c @@ -149,8 +149,7 @@ ip4_create_fib_with_table_id (u32 table_id) fib_table_entry_special_add(fib_table->ft_index, &prefix, ip4_specials[ii].ift_source, - ip4_specials[ii].ift_flag, - ADJ_INDEX_INVALID); + ip4_specials[ii].ift_flag); } return (fib_table->ft_index); diff --git a/src/vnet/fib/ip6_fib.c b/src/vnet/fib/ip6_fib.c index 00297140..d00f4c55 100644 --- a/src/vnet/fib/ip6_fib.c +++ b/src/vnet/fib/ip6_fib.c @@ -35,8 +35,7 @@ vnet_ip6_fib_init (u32 fib_index) fib_table_entry_special_add(fib_index, &pfx, FIB_SOURCE_DEFAULT_ROUTE, - FIB_ENTRY_FLAG_DROP, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_DROP); /* * all link local for us @@ -47,8 +46,7 @@ vnet_ip6_fib_init (u32 fib_index) fib_table_entry_special_add(fib_index, &pfx, FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_LOCAL, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOCAL); } static u32 diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index 91a3899f..d574e596 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -427,8 +427,7 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, fib_table_entry_special_add(outer_fib_index, &t->tunnel_dst, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); t->sibling_index = fib_entry_child_add(t->fib_entry_index, FIB_NODE_TYPE_GRE_TUNNEL, diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index e42b3637..0f562037 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -732,16 +732,14 @@ ip4_add_interface_routes (u32 sw_if_index, &net_pfx, FIB_SOURCE_INTERFACE, (FIB_ENTRY_FLAG_DROP | - FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); net_pfx.fp_addr.ip4.as_u32 |= ~im->fib_masks[pfx.fp_len]; if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32) fib_table_entry_special_add(fib_index, &net_pfx, FIB_SOURCE_INTERFACE, (FIB_ENTRY_FLAG_DROP | - FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); } else if (pfx.fp_len == 31) { diff --git a/src/vnet/ip/ip4_source_check.c b/src/vnet/ip/ip4_source_check.c index 63b7594d..17a1cb1b 100644 --- a/src/vnet/ip/ip4_source_check.c +++ b/src/vnet/ip/ip4_source_check.c @@ -509,7 +509,7 @@ ip_source_check_accept (vlib_main_t * vm, fib_table_entry_special_add (fib_index, &pfx, FIB_SOURCE_URPF_EXEMPT, - FIB_ENTRY_FLAG_DROP, ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_DROP); } else { diff --git a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c b/src/vnet/lisp-gpe/lisp_gpe_tunnel.c index 444bfe14..dd6c6fdd 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c +++ b/src/vnet/lisp-gpe/lisp_gpe_tunnel.c @@ -179,8 +179,7 @@ lisp_gpe_tunnel_find_or_create_and_lock (const locator_pair_t * pair, lgt->fib_entry_index = fib_table_entry_special_add (rloc_fib_index, &pfx, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); hash_set_mem (lisp_gpe_tunnel_db, &lgt->key, (lgt - lisp_gpe_tunnel_pool)); diff --git a/src/vnet/map/map.c b/src/vnet/map/map.c index 811a0abc..6a707df1 100644 --- a/src/vnet/map/map.c +++ b/src/vnet/map/map.c @@ -518,9 +518,7 @@ map_fib_resolve (map_main_pre_resolved_t * pr, pr->fei = fib_table_entry_special_add (0, // default fib &pfx, - FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, - ADJ_INDEX_INVALID); + FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE); pr->sibling = fib_entry_child_add (pr->fei, FIB_NODE_TYPE_MAP_E, proto); map_stack (pr); } diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c index 61cb13c9..1b3df2a8 100644 --- a/src/vnet/vxlan/vxlan.c +++ b/src/vnet/vxlan/vxlan.c @@ -486,7 +486,7 @@ int vnet_vxlan_add_del_tunnel vtep_addr_ref(&t->src); t->fib_entry_index = fib_table_entry_special_add (t->encap_fib_index, &tun_dst_pfx, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); t->sibling_index = fib_entry_child_add (t->fib_entry_index, FIB_NODE_TYPE_VXLAN_TUNNEL, t - vxm->tunnels); vxlan_tunnel_restack_dpo(t); -- cgit 1.2.3-korg