X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip4_forward.c;h=acff66d994b59a79e6a2ae03939004ac39e0b13e;hb=59f71132edffcfa1b94c400736575bd55bdbd7d7;hp=7471a001e7a706502c53c8034a18facd1283b961;hpb=03c254ec70917290b2fde27de1e7b37abe508ade;p=vpp.git diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 7471a001e7a..acff66d994b 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -680,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 */ @@ -720,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, @@ -733,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, @@ -747,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; } })); } @@ -754,10 +763,70 @@ 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; @@ -778,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); @@ -903,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"), }; @@ -1990,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; @@ -2016,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; @@ -2181,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 { @@ -2203,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 { @@ -2347,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)); @@ -2446,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));