vec_elt (im->fib_index_by_sw_if_index, sw_if_index));
vec_add1 (addr_fib, ip4_af);
- /* FIXME-LATER
+ /*
* there is no support for adj-fib handling in the presence of overlapping
* subnets on interfaces. Easy fix - disallow overlapping subnets, like
* most routers do.
if (!is_del)
{
/* When adding an address check that it does not conflict
- with an existing address. */
+ with an existing address on any interface in this table. */
ip_interface_address_t *ia;
- foreach_ip_interface_address
- (&im->lookup_main, ia, sw_if_index,
- 0 /* honor unnumbered */ ,
- ({
- 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,
- x,
- address,
- address_length))
- return
- clib_error_create
- ("failed to add %U which conflicts with %U for interface %U",
- format_ip4_address_and_length, address,
- address_length,
- format_ip4_address_and_length, x,
- ia->address_length,
- format_vnet_sw_if_index_name, vnm,
- sw_if_index);
- }));
+ vnet_sw_interface_t *sif;
+
+ pool_foreach(sif, vnm->interface_main.sw_interfaces,
+ ({
+ if (im->fib_index_by_sw_if_index[sw_if_index] ==
+ im->fib_index_by_sw_if_index[sif->sw_if_index])
+ {
+ foreach_ip_interface_address
+ (&im->lookup_main, ia, sif->sw_if_index,
+ 0 /* honor unnumbered */ ,
+ ({
+ 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,
+ x,
+ address,
+ address_length))
+ {
+ vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
+
+ return
+ clib_error_create
+ ("failed to add %U which conflicts with %U for interface %U",
+ format_ip4_address_and_length, address,
+ address_length,
+ format_ip4_address_and_length, x,
+ ia->address_length,
+ format_vnet_sw_if_index_name, vnm,
+ sif->sw_if_index);
+ }
+ }));
+ }
+ }));
}
/* *INDENT-ON* */
#define IP4_MCAST_ADDR_MASK 0xffff7f00
#endif
+always_inline void
+ip4_mtu_check (vlib_buffer_t * b, u16 packet_len,
+ u16 adj_packet_bytes, bool df, u32 * next, u32 * error)
+{
+ if (packet_len > adj_packet_bytes)
+ {
+ *error = IP4_ERROR_MTU_EXCEEDED;
+ if (df)
+ {
+ icmp4_error_set_vnet_buffer
+ (b, ICMP4_destination_unreachable,
+ ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
+ adj_packet_bytes);
+ *next = IP4_REWRITE_NEXT_ICMP_ERROR;
+ }
+ else
+ {
+ /* Add support for fragmentation here */
+ *next = IP4_REWRITE_NEXT_DROP;
+ }
+ }
+}
+
always_inline uword
ip4_rewrite_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
/* Check MTU of outgoing interface. */
- if (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].rewrite_header.max_l3_packet_bytes)
- {
- error0 = IP4_ERROR_MTU_EXCEEDED;
- next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
- if (vlib_buffer_length_in_chain (vm, p1) >
- adj1[0].rewrite_header.max_l3_packet_bytes)
- {
- error1 = IP4_ERROR_MTU_EXCEEDED;
- next1 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p1, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
+ ip4_mtu_check (p0, clib_net_to_host_u16 (ip0->length),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ ip0->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next0, &error0);
+ ip4_mtu_check (p1, clib_net_to_host_u16 (ip1->length),
+ adj1[0].rewrite_header.max_l3_packet_bytes,
+ ip1->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next1, &error1);
if (is_mcast)
{
vlib_buffer_length_in_chain (vm, p0) + rw_len0);
/* Check MTU of outgoing interface. */
- if (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].rewrite_header.max_l3_packet_bytes)
- {
- error0 = IP4_ERROR_MTU_EXCEEDED;
- next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
+ ip4_mtu_check (p0, clib_net_to_host_u16 (ip0->length),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ ip0->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next0, &error0);
+
if (is_mcast)
{
error0 = ((adj0[0].rewrite_header.sw_if_index ==