X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fvnet%2Fip%2Fip4_forward.c;h=ea78d550789efb77893aaf93b060e2802b93e5ac;hb=4ec36c5535849a4e456ed99b57968d54d5e03b62;hp=a67b0618f86dc037a9f720facc1c47d5bb0fa07c;hpb=960eeea7ea48d91c1f2ec3a85a7a84f56619be2a;p=vpp.git diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index a67b0618f86..ea78d550789 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -49,13 +49,16 @@ #include /* for FIB table and entry creation */ #include /* for FIB uRPF check */ #include +#include #include #include #include #include /* for mFIB table and entry creation */ +#include #include #include +#include /** @brief IPv4 lookup node. @node ip4-lookup @@ -678,7 +681,7 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, ip4_main_t *im = &ip4_main; ip_lookup_main_t *lm = &im->lookup_main; clib_error_t *error = 0; - u32 if_address_index, elts_before; + u32 if_address_index; ip4_address_fib_t ip4_af, *addr_fib = 0; /* local0 interface doesn't support IP addressing */ @@ -718,6 +721,7 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, ip4_address_t * x = ip_interface_address_get_address (&im->lookup_main, ia); + if (ip4_destination_matches_route (im, address, x, ia->address_length) || ip4_destination_matches_route (im, @@ -731,11 +735,18 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, (x->as_u32 != address->as_u32)) continue; + if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) + /* if the address we're comparing against is stale + * then the CP has not added this one back yet, maybe + * it never will, so we have to assume it won't and + * ignore it. if it does add it back, then it will fail + * because this one is now present */ + continue; + /* error if the length or intf was different */ - vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS; + vnm->api_errno = VNET_API_ERROR_ADDRESS_IN_USE; - return - clib_error_create + error = clib_error_create ("failed to add %U on %U which conflicts with %U for interface %U", format_ip4_address_and_length, address, address_length, @@ -745,6 +756,7 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, ia->address_length, format_vnet_sw_if_index_name, vnm, sif->sw_if_index); + goto done; } })); } @@ -752,14 +764,75 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, } /* *INDENT-ON* */ - elts_before = pool_elts (lm->if_address_pool); + if_address_index = ip_interface_address_find (lm, addr_fib, address_length); + + if (is_del) + { + if (~0 == if_address_index) + { + vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE; + error = clib_error_create ("%U not found for interface %U", + lm->format_address_and_length, + addr_fib, address_length, + format_vnet_sw_if_index_name, vnm, + sw_if_index); + goto done; + } + + ip_interface_address_del (lm, if_address_index, addr_fib); + } + else + { + if (~0 != if_address_index) + { + ip_interface_address_t *ia; + + ia = pool_elt_at_index (lm->if_address_pool, if_address_index); + + if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) + { + if (ia->sw_if_index == sw_if_index) + { + /* re-adding an address during the replace action. + * consdier this the update. clear the flag and + * we're done */ + ia->flags &= ~IP_INTERFACE_ADDRESS_FLAG_STALE; + goto done; + } + else + { + /* The prefix is moving from one interface to another. + * delete the stale and add the new */ + ip4_add_del_interface_address_internal (vm, + ia->sw_if_index, + address, + address_length, 1); + ia = NULL; + error = ip_interface_address_add (lm, sw_if_index, + addr_fib, address_length, + &if_address_index); + } + } + else + { + vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS; + error = clib_error_create + ("Prefix %U already found on interface %U", + lm->format_address_and_length, addr_fib, address_length, + format_vnet_sw_if_index_name, vnm, ia->sw_if_index); + } + } + else + error = ip_interface_address_add (lm, sw_if_index, + addr_fib, address_length, + &if_address_index); + } - error = ip_interface_address_add_del - (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index); if (error) goto done; ip4_sw_interface_enable_disable (sw_if_index, !is_del); + ip4_mfib_interface_enable_disable (sw_if_index, !is_del); /* intf addr routes are added/deleted on admin up/down */ if (vnet_sw_interface_is_admin_up (vnm, sw_if_index)) @@ -775,14 +848,10 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm, (lm->if_address_pool, if_address_index)); } - /* If pool did not grow/shrink: add duplicate address. */ - if (elts_before != pool_elts (lm->if_address_pool)) - { - ip4_add_del_interface_address_callback_t *cb; - vec_foreach (cb, im->add_del_interface_address_callbacks) - cb->function (im, cb->function_opaque, sw_if_index, - address, address_length, if_address_index, is_del); - } + ip4_add_del_interface_address_callback_t *cb; + vec_foreach (cb, im->add_del_interface_address_callbacks) + cb->function (im, cb->function_opaque, sw_if_index, + address, address_length, if_address_index, is_del); done: vec_free (addr_fib); @@ -900,20 +969,6 @@ VNET_FEATURE_INIT (ip4_inacl, static) = { .arc_name = "ip4-unicast", .node_name = "ip4-inacl", - .runs_before = VNET_FEATURES ("ip4-source-check-via-rx"), -}; - -VNET_FEATURE_INIT (ip4_source_check_1, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "ip4-source-check-via-rx", - .runs_before = VNET_FEATURES ("ip4-source-check-via-any"), -}; - -VNET_FEATURE_INIT (ip4_source_check_2, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "ip4-source-check-via-any", .runs_before = VNET_FEATURES ("ip4-policer-classify"), }; @@ -1060,6 +1115,7 @@ ip4_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) ip4_add_del_interface_address(vm, sw_if_index, address, ia->address_length, 1); })); /* *INDENT-ON* */ + ip4_mfib_interface_enable_disable (sw_if_index, 0); } vnet_feature_enable_disable ("ip4-unicast", "ip4-not-enabled", sw_if_index, @@ -1504,8 +1560,8 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0, * vnet_buffer()->ip.adj_index[VLIB_TX] will be set to the index of the * adjacency for the source address (the remote sender's address) */ - if (PREDICT_FALSE (last_check->first || - (last_check->src.as_u32 != ip0->src_address.as_u32))) + if (PREDICT_TRUE (last_check->src.as_u32 != ip0->src_address.as_u32) || + last_check->first) { mtrie0 = &ip4_fib_get (vnet_buffer (b)->ip.fib_index)->mtrie; leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, &ip0->src_address); @@ -1542,6 +1598,7 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0, last_check->src.as_u32 = ip0->src_address.as_u32; last_check->lbi = lbi0; last_check->error = *error0; + last_check->first = 0; } else { @@ -1549,7 +1606,6 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0, vnet_buffer (b)->ip.adj_index[VLIB_TX]; vnet_buffer (b)->ip.adj_index[VLIB_TX] = last_check->lbi; *error0 = last_check->error; - last_check->first = 0; } } @@ -1584,7 +1640,7 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip, * vnet_buffer()->ip.adj_index[VLIB_TX] will be set to the index of the * adjacency for the source address (the remote sender's address) */ - if (PREDICT_FALSE (not_last_hit)) + if (PREDICT_TRUE (not_last_hit)) { mtrie[0] = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; mtrie[1] = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie; @@ -1638,6 +1694,7 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip, last_check->src.as_u32 = ip[1]->src_address.as_u32; last_check->lbi = lbi[1]; last_check->error = error[1]; + last_check->first = 0; } else { @@ -1651,7 +1708,6 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip, error[0] = last_check->error; error[1] = last_check->error; - last_check->first = 0; } } @@ -1695,7 +1751,7 @@ ip4_local_inline (vlib_main_t * vm, { u32 *from, n_left_from; vlib_node_runtime_t *error_node = - vlib_node_get_runtime (vm, ip4_input_node.index); + vlib_node_get_runtime (vm, ip4_local_node.index); u16 nexts[VLIB_FRAME_SIZE], *next; vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; ip4_header_t *ip[2]; @@ -1824,6 +1880,8 @@ VLIB_REGISTER_NODE (ip4_local_node) = .name = "ip4-local", .vector_size = sizeof (u32), .format_trace = format_ip4_forward_next_trace, + .n_errors = IP4_N_ERROR, + .error_strings = ip4_error_strings, .n_next_nodes = IP_LOCAL_N_NEXT, .next_nodes = { @@ -1930,349 +1988,6 @@ VLIB_CLI_COMMAND (show_ip_local, static) = }; /* *INDENT-ON* */ -always_inline uword -ip4_arp_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, int is_glean) -{ - vnet_main_t *vnm = vnet_get_main (); - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - u32 *from, *to_next_drop; - uword n_left_from, n_left_to_next_drop, next_index; - u32 thread_index = vm->thread_index; - u64 seed; - - if (node->flags & VLIB_NODE_FLAG_TRACE) - ip4_forward_next_trace (vm, node, frame, VLIB_TX); - - seed = throttle_seed (&im->arp_throttle, thread_index, vlib_time_now (vm)); - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - if (next_index == IP4_ARP_NEXT_DROP) - next_index = IP4_ARP_N_NEXT; /* point to first interface */ - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, IP4_ARP_NEXT_DROP, - to_next_drop, n_left_to_next_drop); - - while (n_left_from > 0 && n_left_to_next_drop > 0) - { - u32 pi0, bi0, adj_index0, sw_if_index0; - ip_adjacency_t *adj0; - vlib_buffer_t *p0, *b0; - ip4_address_t resolve0; - ethernet_arp_header_t *h0; - vnet_hw_interface_t *hw_if0; - u64 r0; - - pi0 = from[0]; - p0 = vlib_get_buffer (vm, pi0); - - from += 1; - n_left_from -= 1; - to_next_drop[0] = pi0; - to_next_drop += 1; - n_left_to_next_drop -= 1; - - adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; - adj0 = adj_get (adj_index0); - - if (is_glean) - { - /* resolve the packet's destination */ - ip4_header_t *ip0 = vlib_buffer_get_current (p0); - resolve0 = ip0->dst_address; - } - else - { - /* resolve the incomplete adj */ - resolve0 = adj0->sub_type.nbr.next_hop.ip4; - } - - /* combine the address and interface for the hash key */ - sw_if_index0 = adj0->rewrite_header.sw_if_index; - r0 = (u64) resolve0.data_u32 << 32; - r0 |= sw_if_index0; - - if (throttle_check (&im->arp_throttle, thread_index, r0, seed)) - { - p0->error = node->errors[IP4_ARP_ERROR_THROTTLED]; - continue; - } - - /* - * the adj has been updated to a rewrite but the node the DPO that got - * us here hasn't - yet. no big deal. we'll drop while we wait. - */ - if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index) - { - p0->error = node->errors[IP4_ARP_ERROR_RESOLVED]; - continue; - } - - /* - * Can happen if the control-plane is programming tables - * with traffic flowing; at least that's today's lame excuse. - */ - if ((is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_GLEAN) - || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP)) - { - p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ]; - continue; - } - /* Send ARP request. */ - h0 = - vlib_packet_template_get_packet (vm, - &im->ip4_arp_request_packet_template, - &bi0); - /* Seems we're out of buffers */ - if (PREDICT_FALSE (!h0)) - { - p0->error = node->errors[IP4_ARP_ERROR_NO_BUFFERS]; - continue; - } - - b0 = vlib_get_buffer (vm, bi0); - - /* copy the persistent fields from the original */ - clib_memcpy_fast (b0->opaque2, p0->opaque2, sizeof (p0->opaque2)); - - /* Add rewrite/encap string for ARP packet. */ - vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t)); - - hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); - - /* Src ethernet address in ARP header. */ - mac_address_from_bytes (&h0->ip4_over_ethernet[0].mac, - hw_if0->hw_address); - if (is_glean) - { - /* The interface's source address is stashed in the Glean Adj */ - h0->ip4_over_ethernet[0].ip4 = - adj0->sub_type.glean.receive_addr.ip4; - } - else - { - /* Src IP address in ARP header. */ - if (ip4_src_address_for_packet (lm, sw_if_index0, - &h0->ip4_over_ethernet[0].ip4)) - { - /* No source address available */ - p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS]; - vlib_buffer_free (vm, &bi0, 1); - continue; - } - } - h0->ip4_over_ethernet[1].ip4 = resolve0; - - p0->error = node->errors[IP4_ARP_ERROR_REQUEST_SENT]; - - vlib_buffer_copy_trace_flag (vm, p0, bi0); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0); - vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; - - vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes); - - vlib_set_next_frame_buffer (vm, node, - adj0->rewrite_header.next_index, bi0); - } - - vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop); - } - - return frame->n_vectors; -} - -VLIB_NODE_FN (ip4_arp_node) (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (ip4_arp_inline (vm, node, frame, 0)); -} - -VLIB_NODE_FN (ip4_glean_node) (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (ip4_arp_inline (vm, node, frame, 1)); -} - -static char *ip4_arp_error_strings[] = { - [IP4_ARP_ERROR_THROTTLED] = "ARP requests throttled", - [IP4_ARP_ERROR_RESOLVED] = "ARP requests resolved", - [IP4_ARP_ERROR_NO_BUFFERS] = "ARP requests out of buffer", - [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent", - [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies", - [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request", -}; - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_arp_node) = -{ - .name = "ip4-arp", - .vector_size = sizeof (u32), - .format_trace = format_ip4_forward_next_trace, - .n_errors = ARRAY_LEN (ip4_arp_error_strings), - .error_strings = ip4_arp_error_strings, - .n_next_nodes = IP4_ARP_N_NEXT, - .next_nodes = - { - [IP4_ARP_NEXT_DROP] = "error-drop", - }, -}; - -VLIB_REGISTER_NODE (ip4_glean_node) = -{ - .name = "ip4-glean", - .vector_size = sizeof (u32), - .format_trace = format_ip4_forward_next_trace, - .n_errors = ARRAY_LEN (ip4_arp_error_strings), - .error_strings = ip4_arp_error_strings, - .n_next_nodes = IP4_ARP_N_NEXT, - .next_nodes = { - [IP4_ARP_NEXT_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -#define foreach_notrace_ip4_arp_error \ -_(THROTTLED) \ -_(RESOLVED) \ -_(NO_BUFFERS) \ -_(REQUEST_SENT) \ -_(NON_ARP_ADJ) \ -_(NO_SOURCE_ADDRESS) - -static clib_error_t * -arp_notrace_init (vlib_main_t * vm) -{ - vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, ip4_arp_node.index); - - /* don't trace ARP request packets */ -#define _(a) \ - vnet_pcap_drop_trace_filter_add_del \ - (rt->errors[IP4_ARP_ERROR_##a], \ - 1 /* is_add */); - foreach_notrace_ip4_arp_error; -#undef _ - return 0; -} - -VLIB_INIT_FUNCTION (arp_notrace_init); - - -#ifndef CLIB_MARCH_VARIANT -/* Send an ARP request to see if given destination is reachable on given interface. */ -clib_error_t * -ip4_probe_neighbor (vlib_main_t * vm, ip4_address_t * dst, u32 sw_if_index, - u8 refresh) -{ - vnet_main_t *vnm = vnet_get_main (); - ip4_main_t *im = &ip4_main; - ethernet_arp_header_t *h; - ip4_address_t *src; - ip_interface_address_t *ia; - ip_adjacency_t *adj; - vnet_hw_interface_t *hi; - vnet_sw_interface_t *si; - vlib_buffer_t *b; - adj_index_t ai; - u32 bi = 0; - u8 unicast_rewrite = 0; - - si = vnet_get_sw_interface (vnm, sw_if_index); - - if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) - { - return clib_error_return (0, "%U: interface %U down", - format_ip4_address, dst, - format_vnet_sw_if_index_name, vnm, - sw_if_index); - } - - src = - ip4_interface_address_matching_destination (im, dst, sw_if_index, &ia); - if (!src) - { - vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE; - return clib_error_return - (0, - "no matching interface address for destination %U (interface %U)", - format_ip4_address, dst, format_vnet_sw_if_index_name, vnm, - sw_if_index); - } - - h = vlib_packet_template_get_packet (vm, - &im->ip4_arp_request_packet_template, - &bi); - - if (!h) - return clib_error_return (0, "ARP request packet allocation failed"); - - hi = vnet_get_sup_hw_interface (vnm, sw_if_index); - if (PREDICT_FALSE (!hi->hw_address)) - { - return clib_error_return (0, "%U: interface %U do not support ip probe", - format_ip4_address, dst, - format_vnet_sw_if_index_name, vnm, - sw_if_index); - } - - mac_address_from_bytes (&h->ip4_over_ethernet[0].mac, hi->hw_address); - - h->ip4_over_ethernet[0].ip4 = src[0]; - h->ip4_over_ethernet[1].ip4 = dst[0]; - - b = vlib_get_buffer (vm, bi); - vnet_buffer (b)->sw_if_index[VLIB_RX] = - vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index; - - ip46_address_t nh = { - .ip4 = *dst, - }; - - ai = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, - VNET_LINK_IP4, &nh, sw_if_index); - adj = adj_get (ai); - - /* Peer has been previously resolved, retrieve glean adj instead */ - if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE) - { - if (refresh) - unicast_rewrite = 1; - else - { - adj_unlock (ai); - ai = adj_glean_add_or_lock (FIB_PROTOCOL_IP4, - VNET_LINK_IP4, sw_if_index, &nh); - adj = adj_get (ai); - } - } - - /* Add encapsulation string for software interface (e.g. ethernet header). */ - vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t)); - if (unicast_rewrite) - { - u16 *etype = vlib_buffer_get_current (b) - 2; - etype[0] = clib_host_to_net_u16 (ETHERNET_TYPE_ARP); - } - vlib_buffer_advance (b, -adj->rewrite_header.data_bytes); - - { - vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index); - u32 *to_next = vlib_frame_vector_args (f); - to_next[0] = bi; - f->n_vectors = 1; - vlib_put_frame_to_node (vm, hi->output_node_index, f); - } - - adj_unlock (ai); - return /* no error */ 0; -} -#endif - typedef enum { IP4_REWRITE_NEXT_DROP, @@ -2327,10 +2042,7 @@ ip4_ttl_inc (vlib_buffer_t * b, ip4_header_t * ip) i32 ttl; u32 checksum; if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)) - { - b->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED; - return; - } + return; ttl = ip->ttl; @@ -2353,10 +2065,7 @@ ip4_ttl_and_checksum_check (vlib_buffer_t * b, ip4_header_t * ip, u16 * next, i32 ttl; u32 checksum; if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)) - { - b->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED; - return; - } + return; ttl = ip->ttl; @@ -2394,8 +2103,7 @@ always_inline uword ip4_rewrite_inline_with_gso (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame, - int do_counters, int is_midchain, int is_mcast, - int do_gso) + int do_counters, int is_midchain, int is_mcast) { ip_lookup_main_t *lm = &ip4_main.lookup_main; u32 *from = vlib_frame_vector_args (frame); @@ -2477,9 +2185,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, u16 ip0_len = clib_net_to_host_u16 (ip0->length); u16 ip1_len = clib_net_to_host_u16 (ip1->length); - if (do_gso && (b[0]->flags & VNET_BUFFER_F_GSO)) + if (b[0]->flags & VNET_BUFFER_F_GSO) ip0_len = gso_mtu_sz (b[0]); - if (do_gso && (b[1]->flags & VNET_BUFFER_F_GSO)) + if (b[1]->flags & VNET_BUFFER_F_GSO) ip1_len = gso_mtu_sz (b[1]); ip4_mtu_check (b[0], ip0_len, @@ -2515,11 +2223,16 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index0, &next_index, b[0]); + vnet_feature_arc_start_w_cfg_index (lm->output_feature_arc_index, + tx_sw_if_index0, + &next_index, b[0], + adj0->ia_cfg_index); + next[0] = next_index; if (is_midchain) - calc_checksums (vm, b[0]); + vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , + 0 /* is_ip6 */ , + 0 /* with gso */ ); } else { @@ -2537,11 +2250,15 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index1, &next_index, b[1]); + vnet_feature_arc_start_w_cfg_index (lm->output_feature_arc_index, + tx_sw_if_index1, + &next_index, b[1], + adj1->ia_cfg_index); next[1] = next_index; if (is_midchain) - calc_checksums (vm, b[1]); + vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , + 0 /* is_ip6 */ , + 0 /* with gso */ ); } else { @@ -2550,9 +2267,14 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, ip4_ttl_inc (b[1], ip1); } - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_two_headers (adj0[0], adj1[0], - ip0, ip1, sizeof (ethernet_header_t)); + if (is_midchain) + /* Guess we are only writing on ipv4 header. */ + vnet_rewrite_two_headers (adj0[0], adj1[0], + ip0, ip1, sizeof (ip4_header_t)); + else + /* Guess we are only writing on simple Ethernet header. */ + vnet_rewrite_two_headers (adj0[0], adj1[0], + ip0, ip1, sizeof (ethernet_header_t)); if (do_counters) { @@ -2573,12 +2295,10 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) { - if (error0 == IP4_ERROR_NONE && adj0->sub_type.midchain.fixup_func) - adj0->sub_type.midchain.fixup_func - (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data); - if (error1 == IP4_ERROR_NONE && adj1->sub_type.midchain.fixup_func) - adj1->sub_type.midchain.fixup_func - (vm, adj1, b[1], adj1->sub_type.midchain.fixup_data); + if (error0 == IP4_ERROR_NONE) + adj_midchain_fixup (vm, adj0, b[0]); + if (error1 == IP4_ERROR_NONE) + adj_midchain_fixup (vm, adj1, b[1]); } if (is_mcast) @@ -2653,7 +2373,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, /* Check MTU of outgoing interface. */ u16 ip0_len = clib_net_to_host_u16 (ip0->length); - if (do_gso && (b[0]->flags & VNET_BUFFER_F_GSO)) + if (b[0]->flags & VNET_BUFFER_F_GSO) ip0_len = gso_mtu_sz (b[0]); ip4_mtu_check (b[0], ip0_len, @@ -2680,15 +2400,25 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index0, &next_index, b[0]); + vnet_feature_arc_start_w_cfg_index (lm->output_feature_arc_index, + tx_sw_if_index0, + &next_index, b[0], + adj0->ia_cfg_index); next[0] = next_index; if (is_midchain) - calc_checksums (vm, b[0]); + { + vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , + 0 /* is_ip6 */ , + 0 /* with gso */ ); - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t)); + /* Guess we are only writing on ipv4 header. */ + vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); + } + else + /* Guess we are only writing on simple Ethernet header. */ + vnet_rewrite_one_header (adj0[0], ip0, + sizeof (ethernet_header_t)); /* * Bump the per-adjacency counters @@ -2700,9 +2430,8 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, adj_index0, 1, vlib_buffer_length_in_chain (vm, b[0]) + rw_len0); - if (is_midchain && adj0->sub_type.midchain.fixup_func) - adj0->sub_type.midchain.fixup_func - (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data); + if (is_midchain) + adj_midchain_fixup (vm, adj0, b[0]); if (is_mcast) /* copy bytes from the IP address into the MAC rewrite */ @@ -2751,7 +2480,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, /* Check MTU of outgoing interface. */ u16 ip0_len = clib_net_to_host_u16 (ip0->length); - if (do_gso && (b[0]->flags & VNET_BUFFER_F_GSO)) + if (b[0]->flags & VNET_BUFFER_F_GSO) ip0_len = gso_mtu_sz (b[0]); ip4_mtu_check (b[0], ip0_len, @@ -2778,16 +2507,26 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index0, &next_index, b[0]); + vnet_feature_arc_start_w_cfg_index (lm->output_feature_arc_index, + tx_sw_if_index0, + &next_index, b[0], + adj0->ia_cfg_index); next[0] = next_index; if (is_midchain) - /* this acts on the packet that is about to be encapped */ - calc_checksums (vm, b[0]); + { + /* this acts on the packet that is about to be encapped */ + vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , + 0 /* is_ip6 */ , + 0 /* with gso */ ); - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t)); + /* Guess we are only writing on ipv4 header. */ + vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); + } + else + /* Guess we are only writing on simple Ethernet header. */ + vnet_rewrite_one_header (adj0[0], ip0, + sizeof (ethernet_header_t)); if (do_counters) vlib_increment_combined_counter @@ -2833,15 +2572,8 @@ ip4_rewrite_inline (vlib_main_t * vm, vlib_frame_t * frame, int do_counters, int is_midchain, int is_mcast) { - vnet_main_t *vnm = vnet_get_main (); - if (PREDICT_FALSE (vnm->interface_main.gso_interface_count > 0)) - return ip4_rewrite_inline_with_gso (vm, node, frame, do_counters, - is_midchain, is_mcast, - 1 /* do_gso */ ); - else - return ip4_rewrite_inline_with_gso (vm, node, frame, do_counters, - is_midchain, is_mcast, - 0 /* no do_gso */ ); + return ip4_rewrite_inline_with_gso (vm, node, frame, do_counters, + is_midchain, is_mcast); }