X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip4_forward.c;h=acff66d994b59a79e6a2ae03939004ac39e0b13e;hb=59f71132edffcfa1b94c400736575bd55bdbd7d7;hp=aa554eab5fbf5e22d099bbf14d8426d96e9707df;hpb=cbe25aab3be72154f2c706c39eeba6a77f34450f;p=vpp.git diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index aa554eab5fb..acff66d994b 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -49,6 +49,7 @@ #include /* for FIB table and entry creation */ #include /* for FIB uRPF check */ #include +#include #include #include #include @@ -56,6 +57,7 @@ #include #include +#include /** @brief IPv4 lookup node. @node ip4-lookup @@ -678,7 +680,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 +720,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 +734,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 +755,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 +763,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 +847,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 +968,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 +1114,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 +1559,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 +1597,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 +1605,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 +1639,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 +1693,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 +1707,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 +1750,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 +1879,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 = { @@ -1984,10 +2041,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; @@ -2010,10 +2064,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; @@ -2175,7 +2226,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, tx_sw_if_index0, &next_index, b[0]); 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 { @@ -2197,7 +2250,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, tx_sw_if_index1, &next_index, b[1]); 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 { @@ -2341,7 +2396,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, 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)); @@ -2440,7 +2497,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) /* this acts on the packet that is about to be encapped */ - 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));