old_adj_index = fib->old_hash_values[0];
/* Avoid spurious reference count increments */
- if (old_adj_index == adj_index)
+ if (old_adj_index == adj_index && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
{
ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
if (adj->share_count > 0)
/* Next hop must be known. */
if (! nh_result)
{
- vnm->api_errno = VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
- error = clib_error_return (0, "next-hop %U/32 not in FIB",
- format_ip4_address, next_hop);
- goto done;
- }
- nh_adj_index = *nh_result;
- }
+ ip_adjacency_t * adj;
+
+ nh_adj_index = ip4_fib_lookup_with_table (im, fib_index,
+ next_hop, 0);
+ adj = ip_get_adjacency (lm, nh_adj_index);
+ /* if ARP interface adjacencty is present, we need to
+ install ARP adjaceny for specific next hop */
+ if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
+ adj->arp.next_hop.ip4.as_u32 == 0)
+ {
+ nh_adj_index = vnet_arp_glean_add(fib_index, next_hop);
+ }
+ else
+ {
+ vnm->api_errno = VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
+ error = clib_error_return (0, "next-hop %U/32 not in FIB",
+ format_ip4_address, next_hop);
+ goto done;
+ }
+ }
+ else
+ nh_adj_index = *nh_result;
+ }
}
else
{
goto done;
}
+ /* Destination is not known and default weight is set so add route
+ to existing non-multipath adjacency */
+ if (dst_adj_index == ~0 && next_hop_weight == 1 && next_hop_sw_if_index == ~0)
+ {
+ /* create new adjacency */
+ ip4_add_del_route_args_t a;
+ a.table_index_or_table_id = fib_index;
+ a.flags = ((is_del ? IP4_ROUTE_FLAG_DEL : IP4_ROUTE_FLAG_ADD)
+ | IP4_ROUTE_FLAG_FIB_INDEX
+ | IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY
+ | (flags & (IP4_ROUTE_FLAG_NO_REDISTRIBUTE
+ | IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP)));
+ a.dst_address = dst_address[0];
+ a.dst_address_length = dst_address_length;
+ a.adj_index = nh_adj_index;
+ a.add_adj = 0;
+ a.n_add_adj = 0;
+
+ ip4_add_del_route (im, &a);
+
+ goto done;
+ }
+
old_mp_adj_index = dst_adj ? dst_adj->heap_handle : ~0;
if (! ip_multipath_adjacency_add_del_next_hop
n = IP_LOOKUP_NEXT_ARP;
node_index = ip4_arp_node.index;
adj->if_address_index = if_address_index;
+ adj->arp.next_hop.ip4.as_u32 = 0;
packet_type = VNET_L3_PACKET_TYPE_ARP;
}
else
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip4_sw_interface_add_del);
+
VLIB_REGISTER_NODE (ip4_lookup_node) = {
.function = ip4_lookup,
.name = "ip4-lookup",
.vector_size = sizeof (u32),
.n_next_nodes = IP_LOOKUP_N_NEXT,
- .next_nodes = {
- [IP_LOOKUP_NEXT_MISS] = "ip4-miss",
- [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_REWRITE] = "ip4-rewrite-transit",
- [IP_LOOKUP_NEXT_CLASSIFY] = "ip4-classify",
- [IP_LOOKUP_NEXT_MAP] = "ip4-map",
- [IP_LOOKUP_NEXT_MAP_T] = "ip4-map-t",
- [IP_LOOKUP_NEXT_SIXRD] = "ip4-sixrd",
- [IP_LOOKUP_NEXT_HOP_BY_HOP] = "ip4-hop-by-hop",
- [IP_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip4-add-hop-by-hop",
- [IP_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip4-pop-hop-by-hop",
- },
+ .next_nodes = IP4_LOOKUP_NEXT_NODES,
};
/* Global IP4 main. */
adj0 = ip_get_adjacency (lm, adj_index0);
ip0 = vlib_buffer_get_current (p0);
+ /* If packet destination is not local, send ARP to next hop */
+ if (adj0->arp.next_hop.ip4.as_u32)
+ ip0->dst_address.data_u32 = adj0->arp.next_hop.ip4.as_u32;
+
/*
* if ip4_rewrite_local applied the IP_LOOKUP_NEXT_ARP
* rewrite to this packet, we need to skip it here.
.vector_size = sizeof (u32),
.n_next_nodes = IP_LOOKUP_N_NEXT,
- .next_nodes = {
- [IP_LOOKUP_NEXT_MISS] = "ip4-miss",
- [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_REWRITE] = "ip4-rewrite-transit",
- [IP_LOOKUP_NEXT_CLASSIFY] = "ip4-classify",
- [IP_LOOKUP_NEXT_MAP] = "ip4-map",
- [IP_LOOKUP_NEXT_MAP_T] = "ip4-map-t",
- [IP_LOOKUP_NEXT_SIXRD] = "ip4-sixrd",
- [IP_LOOKUP_NEXT_HOP_BY_HOP] = "ip4-hop-by-hop",
- [IP_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip4-add-hop-by-hop",
- [IP_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip4-pop-hop-by-hop",
- },
+ .next_nodes = IP4_LOOKUP_NEXT_NODES,
};
VLIB_REGISTER_NODE (ip4_multicast_node,static) = {