fib: Source Address Selection
Type: feature
Use the FIB to provide SAS (in so far as it is today)
- Use the glean adjacency as the record of the connected prefixes
= there's a glean per-{interface, protocol, connected-prefix}
- Keep the glean up to date with whatever the recieve host prefix is
(since it can change)
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Change-Id: I0f3dd1edb1f3fc965af1c7c586709028eb9cdeac
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <igmp/igmp_pkt.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
|
||||
static void
|
||||
vlib_buffer_append (vlib_buffer_t * b, uword l)
|
||||
@@ -76,8 +77,7 @@ igmp_pkt_build_ip_header (igmp_pkt_build_t * bk,
|
||||
ip4->protocol = IP_PROTOCOL_IGMP;
|
||||
ip4->tos = 0xc0;
|
||||
|
||||
ip4_src_address_for_packet (&ip4_main.lookup_main,
|
||||
bk->sw_if_index, &ip4->src_address);
|
||||
fib_sas4_get (bk->sw_if_index, NULL, &ip4->src_address);
|
||||
|
||||
vlib_buffer_append (b, sizeof (*ip4));
|
||||
bk->n_avail -= sizeof (*ip4);
|
||||
|
||||
+8
-10
@@ -18,7 +18,7 @@
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/fib/ip6_fib.h>
|
||||
#include <vnet/fib/ip4_fib.h>
|
||||
#include <vnet/fib/fib_entry.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
#include <vnet/ip/ip6_link.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <vpp/app/version.h>
|
||||
@@ -725,24 +725,22 @@ ip46_fill_l3_header (ip46_address_t * pa46, vlib_buffer_t * b0, int is_ip6)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
ip46_set_src_address (u32 sw_if_index, vlib_buffer_t * b0, int is_ip6)
|
||||
{
|
||||
int res;
|
||||
bool res = false;
|
||||
|
||||
if (is_ip6)
|
||||
{
|
||||
ip6_header_t *ip6 = vlib_buffer_get_current (b0);
|
||||
res = ip6_src_address_for_packet (sw_if_index,
|
||||
&ip6->dst_address, &ip6->src_address);
|
||||
|
||||
res = fib_sas6_get (sw_if_index, &ip6->dst_address, &ip6->src_address);
|
||||
}
|
||||
else
|
||||
{
|
||||
ip4_main_t *im = &ip4_main;
|
||||
ip4_header_t *ip4 = vlib_buffer_get_current (b0);
|
||||
res = ip4_src_address_for_packet (&im->lookup_main,
|
||||
sw_if_index, &ip4->src_address);
|
||||
/* IP4 and IP6 paths have the inverse logic. Harmonize. */
|
||||
res = !res;
|
||||
|
||||
res = fib_sas4_get (sw_if_index, &ip4->dst_address, &ip4->src_address);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -898,9 +898,6 @@ fib_test_v4 (void)
|
||||
adj = adj_get(ai);
|
||||
FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
|
||||
"attached interface adj is glean");
|
||||
FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
|
||||
&adj->sub_type.glean.receive_addr)),
|
||||
"attached interface adj is receive ok");
|
||||
|
||||
local_pfx.fp_len = 32;
|
||||
fib_table_entry_update_one_path(fib_index, &local_pfx,
|
||||
@@ -937,6 +934,9 @@ fib_test_v4 (void)
|
||||
FIB_PROTOCOL_IP4,
|
||||
FIB_SOURCE_INTERFACE)),
|
||||
"2 Interface Source'd prefixes");
|
||||
FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
|
||||
&adj->sub_type.glean.rx_pfx.fp_addr)),
|
||||
"attached interface adj is receive ok");
|
||||
|
||||
/*
|
||||
* +2 interface routes +2 non-shared path-lists
|
||||
@@ -4495,9 +4495,6 @@ fib_test_v6 (void)
|
||||
adj = adj_get(ai);
|
||||
FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
|
||||
"attached interface adj is glean");
|
||||
FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
|
||||
&adj->sub_type.glean.receive_addr)),
|
||||
"attached interface adj is receive ok");
|
||||
dpo = fib_entry_contribute_ip_forwarding(fei);
|
||||
FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
|
||||
1,
|
||||
@@ -4535,6 +4532,9 @@ fib_test_v6 (void)
|
||||
1,
|
||||
&local_pfx.fp_addr.ip6)),
|
||||
"local-route; fwd and non-fwd tables match");
|
||||
FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
|
||||
&adj->sub_type.glean.rx_pfx.fp_addr)),
|
||||
"attached interface adj is receive ok");
|
||||
|
||||
/*
|
||||
* +2 entries. +2 unshared path-lists
|
||||
@@ -5257,6 +5257,8 @@ fib_test_v6 (void)
|
||||
|
||||
FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
|
||||
adj_nbr_db_size());
|
||||
FIB_TEST((0 == adj_glean_db_size()), "ADJ DB size is %d",
|
||||
adj_glean_db_size());
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <vnet/ip/ip4_packet.h>
|
||||
#include <vnet/ip/ip6_link.h>
|
||||
#include <vnet/ethernet/arp_packet.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <vrrp/vrrp.h>
|
||||
#include <vrrp/vrrp_packet.h>
|
||||
@@ -119,8 +120,7 @@ vrrp_vr_addr_cmp (vrrp_vr_t * vr, vrrp_header_t * pkt)
|
||||
peer_addr = &(((ip4_header_t *) pkt) - 1)->src_address;
|
||||
local_addr = &addr.ip4;
|
||||
addr_size = 4;
|
||||
ip4_src_address_for_packet (&ip4_main.lookup_main,
|
||||
vrc->sw_if_index, local_addr);
|
||||
fib_sas4_get (vrc->sw_if_index, NULL, local_addr);
|
||||
}
|
||||
|
||||
return memcmp (local_addr, peer_addr, addr_size);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <vnet/adj/adj.h>
|
||||
#include <vnet/adj/adj_mcast.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
#include <vnet/ip/igmp_packet.h>
|
||||
#include <vnet/ip/ip6_link.h>
|
||||
#include <vnet/ethernet/arp_packet.h>
|
||||
@@ -107,8 +108,7 @@ vrrp_adv_l3_build (vrrp_vr_t * vr, vlib_buffer_t * b,
|
||||
ip4->ttl = 255;
|
||||
ip4->protocol = IP_PROTOCOL_VRRP;
|
||||
clib_memcpy (&ip4->dst_address, &dst->ip4, sizeof (dst->ip4));
|
||||
ip4_src_address_for_packet (&ip4_main.lookup_main,
|
||||
vr->config.sw_if_index, &ip4->src_address);
|
||||
fib_sas4_get (vr->config.sw_if_index, NULL, &ip4->src_address);
|
||||
ip4->length = clib_host_to_net_u16 (sizeof (*ip4) +
|
||||
vrrp_adv_payload_len (vr));
|
||||
ip4->checksum = ip4_header_checksum (ip4);
|
||||
@@ -541,8 +541,7 @@ vrrp_igmp_pkt_build (vrrp_vr_t * vr, vlib_buffer_t * b)
|
||||
|
||||
ip4 = vlib_buffer_get_current (b);
|
||||
clib_memcpy (ip4, &igmp_ip4_mcast, sizeof (*ip4));
|
||||
ip4_src_address_for_packet (&ip4_main.lookup_main, vr->config.sw_if_index,
|
||||
&ip4->src_address);
|
||||
fib_sas4_get (vr->config.sw_if_index, NULL, &ip4->src_address);
|
||||
|
||||
vlib_buffer_chain_increase_length (b, b, sizeof (*ip4));
|
||||
vlib_buffer_advance (b, sizeof (*ip4));
|
||||
|
||||
@@ -1195,6 +1195,7 @@ list(APPEND VNET_SOURCES
|
||||
fib/fib_path_list.c
|
||||
fib/fib_path.c
|
||||
fib/fib_path_ext.c
|
||||
fib/fib_sas.c
|
||||
fib/fib_source.c
|
||||
fib/fib_urpf_list.c
|
||||
fib/fib_attached_export.c
|
||||
@@ -1213,6 +1214,7 @@ list(APPEND VNET_HEADERS
|
||||
fib/fib_node_list.h
|
||||
fib/fib_entry.h
|
||||
fib/fib_entry_delegate.h
|
||||
fib/fib_sas.h
|
||||
fib/fib_source.h
|
||||
)
|
||||
|
||||
|
||||
+1
-2
@@ -288,8 +288,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
|
||||
adj->rewrite_header.sw_if_index);
|
||||
break;
|
||||
case IP_LOOKUP_NEXT_GLEAN:
|
||||
adj_glean_remove(adj->ia_nh_proto,
|
||||
adj->rewrite_header.sw_if_index);
|
||||
adj_glean_remove(adj);
|
||||
break;
|
||||
case IP_LOOKUP_NEXT_MCAST_MIDCHAIN:
|
||||
adj_midchain_teardown(adj);
|
||||
|
||||
+1
-1
@@ -297,7 +297,7 @@ typedef struct ip_adjacency_t_
|
||||
*/
|
||||
struct
|
||||
{
|
||||
ip46_address_t receive_addr;
|
||||
fib_prefix_t rx_pfx;
|
||||
} glean;
|
||||
} sub_type;
|
||||
|
||||
|
||||
+243
-69
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,7 @@
|
||||
extern adj_index_t adj_glean_add_or_lock(fib_protocol_t proto,
|
||||
vnet_link_t linkt,
|
||||
u32 sw_if_index,
|
||||
const ip46_address_t *nh_addr);
|
||||
const fib_prefix_t *conn);
|
||||
|
||||
/**
|
||||
* @brief Get an existing glean
|
||||
@@ -54,7 +54,8 @@ extern adj_index_t adj_glean_add_or_lock(fib_protocol_t proto,
|
||||
* @return INVALID if it does not exist
|
||||
*/
|
||||
extern adj_index_t adj_glean_get(fib_protocol_t proto,
|
||||
u32 sw_if_index);
|
||||
u32 sw_if_index,
|
||||
const ip46_address_t *nh_addr);
|
||||
|
||||
/**
|
||||
* adj_glean_update_rewrite
|
||||
@@ -66,16 +67,37 @@ extern adj_index_t adj_glean_get(fib_protocol_t proto,
|
||||
* glean behaviour on an adjacency liked to a connected prefix.
|
||||
*/
|
||||
extern void adj_glean_update_rewrite(adj_index_t adj_index);
|
||||
extern void adj_glean_update_rewrite_itf(u32 sw_if_index);
|
||||
|
||||
/**
|
||||
* Return the source address from the glean
|
||||
*/
|
||||
const ip46_address_t *adj_glean_get_src(fib_protocol_t proto,
|
||||
u32 sw_if_index,
|
||||
const ip46_address_t *nh_addr);
|
||||
|
||||
/**
|
||||
* @brief Format/display a glean adjacency.
|
||||
*/
|
||||
extern u8* format_adj_glean(u8* s, va_list *ap);
|
||||
|
||||
/**
|
||||
* Walk all the gleans on an interface
|
||||
*/
|
||||
extern void adj_glean_walk (u32 sw_if_index,
|
||||
adj_walk_cb_t,
|
||||
void *);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Module initialisation
|
||||
*/
|
||||
extern void adj_glean_module_init(void);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Return the size of the adjacency database. for testing purposes
|
||||
*/
|
||||
extern u32 adj_glean_db_size(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -120,8 +120,7 @@ extern void adj_nbr_remove(adj_index_t ai,
|
||||
vnet_link_t link_type,
|
||||
const ip46_address_t *nh_addr,
|
||||
u32 sw_if_index);
|
||||
extern void adj_glean_remove(fib_protocol_t proto,
|
||||
u32 sw_if_index);
|
||||
extern void adj_glean_remove(ip_adjacency_t *adj);
|
||||
extern void adj_mcast_remove(fib_protocol_t proto,
|
||||
u32 sw_if_index);
|
||||
extern void adj_midchain_teardown(ip_adjacency_t *adj);
|
||||
|
||||
@@ -127,7 +127,7 @@ fib_entry_src_find_i (const fib_entry_t *fib_entry,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static fib_entry_src_t *
|
||||
fib_entry_src_t *
|
||||
fib_entry_src_find (const fib_entry_t *fib_entry,
|
||||
fib_source_t source)
|
||||
|
||||
@@ -1491,7 +1491,8 @@ fib_path_is_attached (const fib_route_path_t *rpath)
|
||||
{
|
||||
return (!0);
|
||||
}
|
||||
else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
|
||||
else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED ||
|
||||
rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
|
||||
{
|
||||
return (!0);
|
||||
}
|
||||
|
||||
@@ -258,6 +258,8 @@ typedef struct fib_entry_src_vft_t_ {
|
||||
extern const fib_entry_src_vft_t*fib_entry_src_get_vft(
|
||||
const fib_entry_src_t *esrc);
|
||||
|
||||
extern fib_entry_src_t * fib_entry_src_find (const fib_entry_t *fib_entry,
|
||||
fib_source_t source);
|
||||
extern u8* fib_entry_src_format(fib_entry_t *entry,
|
||||
fib_source_t source,
|
||||
u8* s);
|
||||
|
||||
@@ -48,6 +48,63 @@ static void
|
||||
fib_entry_src_interface_remove (fib_entry_src_t *src)
|
||||
{
|
||||
src->fes_pl = FIB_NODE_INDEX_INVALID;
|
||||
ASSERT(src->u.interface.fesi_sibling == ~0);
|
||||
}
|
||||
|
||||
static int
|
||||
fib_entry_src_interface_update_glean (fib_entry_t *cover,
|
||||
const fib_entry_t *local)
|
||||
{
|
||||
fib_entry_src_t *src;
|
||||
adj_index_t ai;
|
||||
|
||||
src = fib_entry_src_find (cover, FIB_SOURCE_INTERFACE);
|
||||
|
||||
if (NULL == src)
|
||||
{
|
||||
/*
|
||||
* The cover is not an interface source, no work
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
ai = fib_path_list_get_adj(src->fes_pl,
|
||||
fib_entry_get_default_chain_type(cover));
|
||||
|
||||
if (INDEX_INVALID != ai)
|
||||
{
|
||||
ip_adjacency_t *adj;
|
||||
|
||||
adj = adj_get(ai);
|
||||
|
||||
if (IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index)
|
||||
{
|
||||
/*
|
||||
* the connected prefix will link to a glean on a non-p2p
|
||||
* interface.
|
||||
* Ensure we are updating with a host in the connected's subnet
|
||||
*/
|
||||
if (fib_prefix_is_cover(&adj->sub_type.glean.rx_pfx,
|
||||
&local->fe_prefix))
|
||||
{
|
||||
adj->sub_type.glean.rx_pfx.fp_addr = local->fe_prefix.fp_addr;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static walk_rc_t
|
||||
fib_entry_src_interface_update_glean_walk (fib_entry_t *cover,
|
||||
fib_node_index_t covered,
|
||||
void *ctx)
|
||||
{
|
||||
if (fib_entry_src_interface_update_glean(cover, fib_entry_get(covered)))
|
||||
return (WALK_STOP);
|
||||
|
||||
return (WALK_CONTINUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -56,37 +113,7 @@ fib_entry_src_interface_path_swap (fib_entry_src_t *src,
|
||||
fib_path_list_flags_t pl_flags,
|
||||
const fib_route_path_t *paths)
|
||||
{
|
||||
fib_node_index_t fib_entry_index;
|
||||
ip_adjacency_t *adj;
|
||||
|
||||
fib_entry_index = fib_entry_get_index(entry);
|
||||
src->fes_pl = fib_path_list_create(pl_flags, paths);
|
||||
|
||||
/*
|
||||
* this is a hack to get the entry's prefix into the glean adjacency
|
||||
* so that it is available for fast retrieval in the switch path.
|
||||
*/
|
||||
if (!(FIB_ENTRY_FLAG_LOCAL & src->fes_entry_flags))
|
||||
{
|
||||
adj_index_t ai;
|
||||
|
||||
ai = fib_path_list_get_adj(src->fes_pl,
|
||||
fib_entry_get_default_chain_type(
|
||||
fib_entry_get(fib_entry_index)));
|
||||
if (INDEX_INVALID != ai)
|
||||
{
|
||||
adj = adj_get(ai);
|
||||
|
||||
if (IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index)
|
||||
{
|
||||
/*
|
||||
* the connected prefix will link to a glean on a non-p2p
|
||||
* u.interface.
|
||||
*/
|
||||
adj->sub_type.glean.receive_addr = entry->fe_prefix.fp_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -116,6 +143,8 @@ fib_entry_src_interface_activate (fib_entry_src_t *src,
|
||||
|
||||
src->u.interface.fesi_sibling =
|
||||
fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
|
||||
|
||||
fib_entry_src_interface_update_glean(cover, fib_entry);
|
||||
}
|
||||
|
||||
return (!0);
|
||||
@@ -142,6 +171,11 @@ fib_entry_src_interface_deactivate (fib_entry_src_t *src,
|
||||
fib_entry_cover_untrack(cover, src->u.interface.fesi_sibling);
|
||||
|
||||
src->u.interface.fesi_cover = FIB_NODE_INDEX_INVALID;
|
||||
src->u.interface.fesi_sibling = ~0;
|
||||
|
||||
fib_entry_cover_walk(cover,
|
||||
fib_entry_src_interface_update_glean_walk,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-2
@@ -245,6 +245,10 @@ typedef struct fib_path_t_ {
|
||||
u32 fp_interface;
|
||||
} attached_next_hop;
|
||||
struct {
|
||||
/**
|
||||
* The Connected local address
|
||||
*/
|
||||
fib_prefix_t fp_connected;
|
||||
/**
|
||||
* The interface
|
||||
*/
|
||||
@@ -732,7 +736,7 @@ fib_path_attached_get_adj (fib_path_t *path,
|
||||
|
||||
ai = adj_glean_add_or_lock(nh_proto, link,
|
||||
path->attached.fp_interface,
|
||||
NULL);
|
||||
&path->attached.fp_connected);
|
||||
dpo_set(dpo, DPO_ADJACENCY_GLEAN, vnet_link_to_dpo_proto(link), ai);
|
||||
adj_unlock(ai);
|
||||
}
|
||||
@@ -1262,6 +1266,8 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_UNREACH;
|
||||
if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_PROHIBIT;
|
||||
if (rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_GLEAN;
|
||||
|
||||
return (cfg_flags);
|
||||
}
|
||||
@@ -1365,6 +1371,12 @@ fib_path_create (fib_node_index_t pl_index,
|
||||
path->fp_type = FIB_PATH_TYPE_SPECIAL;
|
||||
path->classify.fp_classify_table_id = rpath->frp_classify_table_id;
|
||||
}
|
||||
else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_GLEAN)
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_ATTACHED;
|
||||
path->attached.fp_interface = rpath->frp_sw_if_index;
|
||||
path->attached.fp_connected = rpath->frp_connected;
|
||||
}
|
||||
else if (~0 != rpath->frp_sw_if_index)
|
||||
{
|
||||
if (ip46_address_is_zero(&rpath->frp_addr))
|
||||
@@ -2105,7 +2117,7 @@ fib_path_resolve (fib_node_index_t path_index)
|
||||
break;
|
||||
}
|
||||
case FIB_PATH_TYPE_DVR:
|
||||
dvr_dpo_add_or_lock(path->attached.fp_interface,
|
||||
dvr_dpo_add_or_lock(path->dvr.fp_interface,
|
||||
path->fp_nh_proto,
|
||||
&path->fp_dpo);
|
||||
break;
|
||||
|
||||
@@ -99,10 +99,14 @@ typedef enum fib_path_cfg_attribute_t_ {
|
||||
* The path pops a Psuedo Wire Control Word
|
||||
*/
|
||||
FIB_PATH_CFG_ATTRIBUTE_POP_PW_CW,
|
||||
/**
|
||||
* The path is a glean
|
||||
*/
|
||||
FIB_PATH_CFG_ATTRIBUTE_GLEAN,
|
||||
/**
|
||||
* Marker. Add new types before this one, then update it.
|
||||
*/
|
||||
FIB_PATH_CFG_ATTRIBUTE_LAST = FIB_PATH_CFG_ATTRIBUTE_POP_PW_CW,
|
||||
FIB_PATH_CFG_ATTRIBUTE_LAST = FIB_PATH_CFG_ATTRIBUTE_GLEAN,
|
||||
} __attribute__ ((packed)) fib_path_cfg_attribute_t;
|
||||
|
||||
/**
|
||||
@@ -123,7 +127,8 @@ typedef enum fib_path_cfg_attribute_t_ {
|
||||
[FIB_PATH_CFG_ATTRIBUTE_INTF_RX] = "interface-rx", \
|
||||
[FIB_PATH_CFG_ATTRIBUTE_RPF_ID] = "rpf-id", \
|
||||
[FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC] = "deag-src", \
|
||||
[FIB_PATH_CFG_ATTRIBUTE_POP_PW_CW] = "pop-pw-cw", \
|
||||
[FIB_PATH_CFG_ATTRIBUTE_POP_PW_CW] = "pop-pw-cw", \
|
||||
[FIB_PATH_CFG_ATTRIBUTE_GLEAN] = "glean", \
|
||||
}
|
||||
|
||||
#define FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(_item) \
|
||||
@@ -149,6 +154,7 @@ typedef enum fib_path_cfg_flags_t_ {
|
||||
FIB_PATH_CFG_FLAG_RPF_ID = (1 << FIB_PATH_CFG_ATTRIBUTE_RPF_ID),
|
||||
FIB_PATH_CFG_FLAG_DEAG_SRC = (1 << FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC),
|
||||
FIB_PATH_CFG_FLAG_POP_PW_CW = (1 << FIB_PATH_CFG_ATTRIBUTE_POP_PW_CW),
|
||||
FIB_PATH_CFG_FLAG_GLEAN = (1 << FIB_PATH_CFG_ATTRIBUTE_GLEAN),
|
||||
} __attribute__ ((packed)) fib_path_cfg_flags_t;
|
||||
|
||||
typedef enum fib_path_format_flags_t_
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief FIB Source Address selection
|
||||
*
|
||||
* Use the FIB for source address selection on an interface
|
||||
*/
|
||||
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
#include <vnet/adj/adj_glean.h>
|
||||
#include <vnet/ip/ip6_link.h>
|
||||
|
||||
|
||||
bool
|
||||
fib_sas_get (u32 sw_if_index,
|
||||
ip_address_family_t af,
|
||||
const ip46_address_t *dst,
|
||||
ip46_address_t *src)
|
||||
{
|
||||
switch (af)
|
||||
{
|
||||
case AF_IP4:
|
||||
if (dst)
|
||||
return (fib_sas4_get(sw_if_index, &dst->ip4, &src->ip4));
|
||||
else
|
||||
return (fib_sas4_get(sw_if_index, NULL, &src->ip4));
|
||||
case AF_IP6:
|
||||
if (dst)
|
||||
return (fib_sas6_get(sw_if_index, &dst->ip6, &src->ip6));
|
||||
else
|
||||
return (fib_sas6_get(sw_if_index, NULL, &src->ip6));
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
fib_sas4_get (u32 sw_if_index,
|
||||
const ip4_address_t *dst,
|
||||
ip4_address_t *src)
|
||||
{
|
||||
ip46_address_t d_tmp, *d_tmpp = NULL;
|
||||
const ip46_address_t *s_tmp;
|
||||
vnet_sw_interface_t *swif;
|
||||
|
||||
if (dst)
|
||||
{
|
||||
d_tmpp = &d_tmp;
|
||||
d_tmp.ip4 = *dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the interface is unnumbered then use the IP interface
|
||||
*/
|
||||
swif = vnet_get_sw_interface (vnet_get_main(), sw_if_index);
|
||||
|
||||
if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
|
||||
sw_if_index = swif->unnumbered_sw_if_index;
|
||||
|
||||
/*
|
||||
* get the source address from the glean adjacency
|
||||
*/
|
||||
s_tmp = adj_glean_get_src (FIB_PROTOCOL_IP4, sw_if_index, d_tmpp);
|
||||
|
||||
if (NULL != s_tmp)
|
||||
{
|
||||
src->as_u32 = s_tmp->ip4.as_u32;
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
fib_sas6_get (u32 sw_if_index,
|
||||
const ip6_address_t *dst,
|
||||
ip6_address_t *src)
|
||||
{
|
||||
ip46_address_t d_tmp, *d_tmpp = NULL;
|
||||
const ip46_address_t *s_tmp;
|
||||
|
||||
if (dst)
|
||||
{
|
||||
d_tmpp = &d_tmp;
|
||||
d_tmp.ip6 = *dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the dst is v6 and link local, use the source link local
|
||||
*/
|
||||
if (ip6_address_is_link_local_unicast (dst))
|
||||
{
|
||||
ip6_address_copy (src, ip6_get_link_local_address (sw_if_index));
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* get the source address from the glean adjacency
|
||||
*/
|
||||
s_tmp = adj_glean_get_src (FIB_PROTOCOL_IP6, sw_if_index, d_tmpp);
|
||||
|
||||
if (NULL != s_tmp)
|
||||
{
|
||||
ip6_address_copy(src, &s_tmp->ip6);
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief FIB Source Address selection
|
||||
*
|
||||
* Use the FIB for source address selection on an interface
|
||||
*/
|
||||
|
||||
#ifndef __FIB_SAS_H__
|
||||
#define __FIB_SAS_H__
|
||||
|
||||
#include <vnet/fib/fib_types.h>
|
||||
#include <vnet/ip/ip_types.h>
|
||||
|
||||
/**
|
||||
* @brief Get a Source address to use in a packet being sent out
|
||||
* an interface
|
||||
*
|
||||
* @param sw_if_index The interface on which the packet is to be sent
|
||||
* @param af The address family of the packet
|
||||
* @param dst The destination of the packet (can be NULL in which case any
|
||||
* of the available address will be returned)
|
||||
* @param src OUT the source address to use
|
||||
*
|
||||
* @return True if an address is available False (and src is unset) otherwise
|
||||
*/
|
||||
extern bool fib_sas_get (u32 sw_if_index,
|
||||
ip_address_family_t af,
|
||||
const ip46_address_t *dst,
|
||||
ip46_address_t *src);
|
||||
|
||||
/**
|
||||
* @brief Get an IPv4 Source address to use in a packet being sent out
|
||||
* an interface
|
||||
*
|
||||
* @param sw_if_index The interface on which the packet is to be sent
|
||||
* @param dst The destination of the packet (can be NULL in which case any
|
||||
* of the available address will be returned)
|
||||
* @param src OUT the source address to use
|
||||
*
|
||||
* @return True if an address is available False (and src is unset) otherwise
|
||||
*/
|
||||
extern bool fib_sas4_get (u32 sw_if_index,
|
||||
const ip4_address_t *dst,
|
||||
ip4_address_t *src);
|
||||
|
||||
/**
|
||||
* @brief Get an IPv6 Source address to use in a packet being sent out
|
||||
* an interface
|
||||
*
|
||||
* @param sw_if_index The interface on which the packet is to be sent
|
||||
* @param dst The destination of the packet (can be NULL in which case any
|
||||
* of the available address will be returned)
|
||||
* @param src OUT the source address to use
|
||||
*
|
||||
* @return True if an address is available False (and src is unset) otherwise
|
||||
*/
|
||||
extern bool fib_sas6_get (u32 sw_if_index,
|
||||
const ip6_address_t *dst,
|
||||
ip6_address_t *src);
|
||||
|
||||
#endif
|
||||
@@ -510,7 +510,7 @@ fib_table_route_path_fixup (const fib_prefix_t *prefix,
|
||||
(~0 == path->frp_sw_if_index) &&
|
||||
(0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
|
||||
{
|
||||
/* Prefix recurses via itse;f */
|
||||
/* Prefix recurses via itself */
|
||||
path->frp_flags |= FIB_ROUTE_PATH_DROP;
|
||||
}
|
||||
if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
|
||||
@@ -522,6 +522,15 @@ fib_table_route_path_fixup (const fib_prefix_t *prefix,
|
||||
path->frp_addr = prefix->fp_addr;
|
||||
path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
|
||||
}
|
||||
else if ((*eflags & FIB_ENTRY_FLAG_CONNECTED) &&
|
||||
!(*eflags & FIB_ENTRY_FLAG_LOCAL))
|
||||
{
|
||||
if (ip46_address_is_zero(&path->frp_addr))
|
||||
{
|
||||
path->frp_flags |= FIB_ROUTE_PATH_GLEAN;
|
||||
fib_prefix_normalize(prefix, &path->frp_connected);
|
||||
}
|
||||
}
|
||||
if (*eflags & FIB_ENTRY_FLAG_DROP)
|
||||
{
|
||||
path->frp_flags |= FIB_ROUTE_PATH_DROP;
|
||||
|
||||
@@ -260,6 +260,25 @@ fib_prefix_is_host (const fib_prefix_t *prefix)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
fib_prefix_normalize (const fib_prefix_t *p,
|
||||
fib_prefix_t *out)
|
||||
{
|
||||
fib_prefix_copy (out, p);
|
||||
|
||||
switch (p->fp_proto)
|
||||
{
|
||||
case FIB_PROTOCOL_IP4:
|
||||
ip4_address_normalize(&out->fp_addr.ip4, out->fp_len);
|
||||
break;
|
||||
case FIB_PROTOCOL_IP6:
|
||||
ip6_address_normalize(&out->fp_addr.ip6, out->fp_len);
|
||||
break;
|
||||
case FIB_PROTOCOL_MPLS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u8 *
|
||||
format_fib_prefix (u8 * s, va_list * args)
|
||||
{
|
||||
|
||||
@@ -266,6 +266,13 @@ extern int fib_prefix_is_cover(const fib_prefix_t *p1,
|
||||
extern int fib_prefix_is_host(const fib_prefix_t *p);
|
||||
extern u8 fib_prefix_get_host_length (fib_protocol_t proto);
|
||||
|
||||
/**
|
||||
* normalise a prefix (i.e. mask the host bits according to the
|
||||
* prefix length)
|
||||
*/
|
||||
extern void fib_prefix_normalize(const fib_prefix_t *p,
|
||||
fib_prefix_t *out);
|
||||
|
||||
/**
|
||||
* \brief Host prefix from ip
|
||||
*/
|
||||
@@ -393,6 +400,10 @@ typedef enum fib_route_path_flags_t_
|
||||
* Pop a Psuedo Wire Control Word
|
||||
*/
|
||||
FIB_ROUTE_PATH_POP_PW_CW = (1 << 18),
|
||||
/**
|
||||
* A path that resolves via a glean adjacency
|
||||
*/
|
||||
FIB_ROUTE_PATH_GLEAN = (1 << 19),
|
||||
} fib_route_path_flags_t;
|
||||
|
||||
/**
|
||||
@@ -520,6 +531,11 @@ typedef struct fib_route_path_t_ {
|
||||
* Present in an mfib path list
|
||||
*/
|
||||
index_t frp_bier_imp;
|
||||
|
||||
/**
|
||||
* Glean prefix on a glean path
|
||||
*/
|
||||
fib_prefix_t frp_connected;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,23 +40,23 @@
|
||||
#include <vnet/ip-neighbor/ip4_neighbor.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vnet/util/throttle.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
|
||||
/** ARP throttling */
|
||||
static throttle_t arp_throttle;
|
||||
|
||||
void
|
||||
ip4_neighbor_probe_dst (const ip_adjacency_t * adj, const ip4_address_t * dst)
|
||||
ip4_neighbor_probe_dst (u32 sw_if_index, const ip4_address_t * dst)
|
||||
{
|
||||
ip_interface_address_t *ia;
|
||||
ip4_address_t *src;
|
||||
ip4_address_t src;
|
||||
adj_index_t ai;
|
||||
|
||||
src = ip4_interface_address_matching_destination
|
||||
(&ip4_main,
|
||||
&adj->sub_type.nbr.next_hop.ip4, adj->rewrite_header.sw_if_index, &ia);
|
||||
if (!src)
|
||||
return;
|
||||
/* any glean will do, it's just for the rewrite */
|
||||
ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index, NULL);
|
||||
|
||||
ip4_neighbor_probe (vlib_get_main (), vnet_get_main (), adj, src, dst);
|
||||
if (ADJ_INDEX_INVALID != ai && fib_sas4_get (sw_if_index, dst, &src))
|
||||
ip4_neighbor_probe (vlib_get_main (),
|
||||
vnet_get_main (), adj_get (ai), &src, dst);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -67,11 +67,12 @@ ip4_neighbor_advertise (vlib_main_t * vm,
|
||||
vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
|
||||
ip4_main_t *i4m = &ip4_main;
|
||||
u8 *rewrite, rewrite_len;
|
||||
ip4_address_t tmp;
|
||||
|
||||
if (NULL == addr)
|
||||
{
|
||||
ip4_main_t *i4m = &ip4_main;
|
||||
addr = ip4_interface_first_address (i4m, sw_if_index, 0);
|
||||
fib_sas4_get (sw_if_index, NULL, &tmp);
|
||||
addr = &tmp;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
@@ -122,8 +123,6 @@ ip4_arp_inline (vlib_main_t * vm,
|
||||
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;
|
||||
@@ -171,14 +170,14 @@ ip4_arp_inline (vlib_main_t * vm,
|
||||
/* resolve the packet's destination */
|
||||
ip4_header_t *ip0 = vlib_buffer_get_current (p0);
|
||||
resolve0 = ip0->dst_address;
|
||||
src0 = adj0->sub_type.glean.receive_addr.ip4;
|
||||
src0 = adj0->sub_type.glean.rx_pfx.fp_addr.ip4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* resolve the incomplete adj */
|
||||
resolve0 = adj0->sub_type.nbr.next_hop.ip4;
|
||||
/* Src IP address in ARP header. */
|
||||
if (ip4_src_address_for_packet (lm, sw_if_index0, &src0))
|
||||
if (!fib_sas4_get (sw_if_index0, &resolve0, &src0))
|
||||
{
|
||||
/* No source address available */
|
||||
p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/ethernet/arp_packet.h>
|
||||
|
||||
extern void ip4_neighbor_probe_dst (const ip_adjacency_t * adj,
|
||||
extern void ip4_neighbor_probe_dst (u32 sw_if_index,
|
||||
const ip4_address_t * dst);
|
||||
extern void ip4_neighbor_advertise (vlib_main_t * vm,
|
||||
vnet_main_t * vnm,
|
||||
|
||||
@@ -17,23 +17,19 @@
|
||||
|
||||
#include <vnet/ip-neighbor/ip6_neighbor.h>
|
||||
#include <vnet/util/throttle.h>
|
||||
#include <vnet/fib/fib_sas.h>
|
||||
|
||||
/** ND throttling */
|
||||
static throttle_t nd_throttle;
|
||||
|
||||
void
|
||||
ip6_neighbor_probe_dst (const ip_adjacency_t * adj, const ip6_address_t * dst)
|
||||
ip6_neighbor_probe_dst (u32 sw_if_index, const ip6_address_t * dst)
|
||||
{
|
||||
ip_interface_address_t *ia;
|
||||
ip6_address_t *src;
|
||||
ip6_address_t src;
|
||||
|
||||
src = ip6_interface_address_matching_destination
|
||||
(&ip6_main, dst, adj->rewrite_header.sw_if_index, &ia);
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
ip6_neighbor_probe (vlib_get_main (), vnet_get_main (), adj, src, dst);
|
||||
if (fib_sas6_get (sw_if_index, dst, &src))
|
||||
ip6_neighbor_probe (vlib_get_main (), vnet_get_main (),
|
||||
sw_if_index, &src, dst);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -210,15 +206,15 @@ ip6_discover_neighbor_inline (vlib_main_t * vm,
|
||||
* Choose source address based on destination lookup
|
||||
* adjacency.
|
||||
*/
|
||||
if (!ip6_src_address_for_packet (sw_if_index0,
|
||||
&ip0->dst_address, &src))
|
||||
if (!fib_sas6_get (sw_if_index0, &ip0->dst_address, &src))
|
||||
{
|
||||
/* There is no address on the interface */
|
||||
p0->error = node->errors[IP6_NBR_ERROR_NO_SOURCE_ADDRESS];
|
||||
continue;
|
||||
}
|
||||
|
||||
b0 = ip6_neighbor_probe (vm, vnm, adj0, &src, &ip0->dst_address);
|
||||
b0 = ip6_neighbor_probe (vm, vnm, sw_if_index0,
|
||||
&src, &ip0->dst_address);
|
||||
|
||||
if (PREDICT_TRUE (NULL != b0))
|
||||
{
|
||||
|
||||
@@ -34,17 +34,18 @@ extern void ip6_neighbor_advertise (vlib_main_t * vm,
|
||||
u32 sw_if_index,
|
||||
const ip6_address_t * addr);
|
||||
|
||||
extern void ip6_neighbor_probe_dst (const ip_adjacency_t * adj,
|
||||
extern void ip6_neighbor_probe_dst (u32 sw_if_index,
|
||||
const ip6_address_t * dst);
|
||||
|
||||
always_inline vlib_buffer_t *
|
||||
ip6_neighbor_probe (vlib_main_t * vm,
|
||||
vnet_main_t * vnm,
|
||||
const ip_adjacency_t * adj,
|
||||
u32 sw_if_index,
|
||||
const ip6_address_t * src, const ip6_address_t * dst)
|
||||
{
|
||||
icmp6_neighbor_solicitation_header_t *h0;
|
||||
vnet_hw_interface_t *hw_if0;
|
||||
const ip_adjacency_t *adj;
|
||||
vlib_buffer_t *b0;
|
||||
int bogus_length;
|
||||
u32 bi0 = 0;
|
||||
@@ -52,17 +53,17 @@ ip6_neighbor_probe (vlib_main_t * vm,
|
||||
h0 = vlib_packet_template_get_packet
|
||||
(vm, &ip6_neighbor_packet_template, &bi0);
|
||||
if (!h0)
|
||||
return NULL;;
|
||||
return NULL;
|
||||
|
||||
/* if the interface has been disabled for ip6, later steps to retrieve
|
||||
* an adjacency will result in a segv.
|
||||
*/
|
||||
if (!ip6_link_is_enabled (adj->rewrite_header.sw_if_index))
|
||||
if (!ip6_link_is_enabled (sw_if_index))
|
||||
return NULL;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
hw_if0 = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
|
||||
hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index);
|
||||
|
||||
/*
|
||||
* Destination address is a solicited node multicast address.
|
||||
@@ -87,11 +88,11 @@ ip6_neighbor_probe (vlib_main_t * vm,
|
||||
ASSERT (bogus_length == 0);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
|
||||
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
|
||||
|
||||
/* Use the link's mcast adj to ship the packet */
|
||||
vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
|
||||
ip6_link_get_mcast_adj (adj->rewrite_header.sw_if_index);
|
||||
ip6_link_get_mcast_adj (sw_if_index);
|
||||
adj = adj_get (vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
|
||||
|
||||
b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
|
||||
|
||||
@@ -1011,22 +1011,19 @@ ip_neighbor_register (ip_address_family_t af, const ip_neighbor_vft_t * vft)
|
||||
}
|
||||
|
||||
void
|
||||
ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * dst)
|
||||
ip_neighbor_probe_dst (u32 sw_if_index,
|
||||
ip_address_family_t af, const ip46_address_t * dst)
|
||||
{
|
||||
if (!vnet_sw_interface_is_admin_up (vnet_get_main (),
|
||||
adj->rewrite_header.sw_if_index))
|
||||
if (!vnet_sw_interface_is_admin_up (vnet_get_main (), sw_if_index))
|
||||
return;
|
||||
|
||||
switch (adj->ia_nh_proto)
|
||||
switch (af)
|
||||
{
|
||||
case FIB_PROTOCOL_IP6:
|
||||
ip6_neighbor_probe_dst (adj, &dst->ip6);
|
||||
case AF_IP6:
|
||||
ip6_neighbor_probe_dst (sw_if_index, &dst->ip6);
|
||||
break;
|
||||
case FIB_PROTOCOL_IP4:
|
||||
ip4_neighbor_probe_dst (adj, &dst->ip4);
|
||||
break;
|
||||
case FIB_PROTOCOL_MPLS:
|
||||
ASSERT (0);
|
||||
case AF_IP4:
|
||||
ip4_neighbor_probe_dst (sw_if_index, &dst->ip4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1034,7 +1031,9 @@ ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * dst)
|
||||
void
|
||||
ip_neighbor_probe (const ip_adjacency_t * adj)
|
||||
{
|
||||
ip_neighbor_probe_dst (adj, &adj->sub_type.nbr.next_hop);
|
||||
ip_neighbor_probe_dst (adj->rewrite_header.sw_if_index,
|
||||
ip_address_family_from_fib_proto (adj->ia_nh_proto),
|
||||
&adj->sub_type.nbr.next_hop);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1147,7 +1146,6 @@ ip_neighbor_ethernet_change_mac (ethernet_main_t * em,
|
||||
u32 sw_if_index, uword opaque)
|
||||
{
|
||||
ip_neighbor_t *ipn;
|
||||
adj_index_t ai;
|
||||
|
||||
IP_NEIGHBOR_DBG ("mac-change: %U",
|
||||
format_vnet_sw_if_index_name, vnet_get_main (),
|
||||
@@ -1165,10 +1163,7 @@ ip_neighbor_ethernet_change_mac (ethernet_main_t * em,
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
|
||||
|
||||
if (ADJ_INDEX_INVALID != ai)
|
||||
adj_glean_update_rewrite (ai);
|
||||
adj_glean_update_rewrite_itf (sw_if_index);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1543,14 +1538,8 @@ ip_neighbour_age_out (index_t ipni, f64 now, f64 * wait)
|
||||
}
|
||||
else
|
||||
{
|
||||
adj_index_t ai;
|
||||
|
||||
ai = adj_glean_get (ip_address_family_to_fib_proto (af),
|
||||
ip_neighbor_get_sw_if_index (ipn));
|
||||
|
||||
if (ADJ_INDEX_INVALID != ai)
|
||||
ip_neighbor_probe_dst (adj_get (ai),
|
||||
&ip_addr_46 (&ipn->ipn_key->ipnk_ip));
|
||||
ip_neighbor_probe_dst (ip_neighbor_get_sw_if_index (ipn),
|
||||
af, &ip_addr_46 (&ipn->ipn_key->ipnk_ip));
|
||||
|
||||
ipn->ipn_n_probes++;
|
||||
*wait = 1;
|
||||
|
||||
@@ -54,7 +54,8 @@ extern void ip_neighbor_learn (const ip_neighbor_learn_t * l);
|
||||
extern void ip_neighbor_update (vnet_main_t * vnm, adj_index_t ai);
|
||||
|
||||
extern void ip_neighbor_probe (const ip_adjacency_t * adj);
|
||||
extern void ip_neighbor_probe_dst (const ip_adjacency_t * adj,
|
||||
extern void ip_neighbor_probe_dst (u32 sw_if_index,
|
||||
ip_address_family_t af,
|
||||
const ip46_address_t * ip);
|
||||
|
||||
extern void ip_neighbor_mark (ip_address_family_t af);
|
||||
|
||||
@@ -201,26 +201,6 @@ ip4_destination_matches_interface (ip4_main_t * im,
|
||||
return ip4_destination_matches_route (im, key, a, ia->address_length);
|
||||
}
|
||||
|
||||
always_inline int
|
||||
ip4_src_address_for_packet (ip_lookup_main_t * lm,
|
||||
u32 sw_if_index, ip4_address_t * src)
|
||||
{
|
||||
u32 if_add_index = lm->if_address_pool_index_by_sw_if_index[sw_if_index];
|
||||
if (PREDICT_TRUE (if_add_index != ~0))
|
||||
{
|
||||
ip_interface_address_t *if_add =
|
||||
pool_elt_at_index (lm->if_address_pool, if_add_index);
|
||||
ip4_address_t *if_ip = ip_interface_address_get_address (lm, if_add);
|
||||
*src = *if_ip;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src->as_u32 = 0;
|
||||
}
|
||||
return (!0);
|
||||
}
|
||||
|
||||
/* Find interface address which matches destination. */
|
||||
always_inline ip4_address_t *
|
||||
ip4_interface_address_matching_destination (ip4_main_t * im,
|
||||
|
||||
+49
-89
@@ -380,28 +380,28 @@ ip4_add_interface_prefix_routes (ip4_main_t *im,
|
||||
mhash_set (&lm->prefix_to_if_prefix_index, &key,
|
||||
if_prefix - lm->if_prefix_pool, 0 /* old value */);
|
||||
|
||||
pfx_special.fp_len = a->address_length;
|
||||
pfx_special.fp_addr.ip4.as_u32 = address->as_u32;
|
||||
|
||||
/* set the glean route for the prefix */
|
||||
fib_table_entry_update_one_path (fib_index, &pfx_special,
|
||||
FIB_SOURCE_INTERFACE,
|
||||
(FIB_ENTRY_FLAG_CONNECTED |
|
||||
FIB_ENTRY_FLAG_ATTACHED),
|
||||
DPO_PROTO_IP4,
|
||||
/* No next-hop address */
|
||||
NULL,
|
||||
sw_if_index,
|
||||
/* invalid FIB index */
|
||||
~0,
|
||||
1,
|
||||
/* no out-label stack */
|
||||
NULL,
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
|
||||
/* length <= 30 - add glean, drop first address, maybe drop bcast address */
|
||||
if (a->address_length <= 30)
|
||||
{
|
||||
pfx_special.fp_len = a->address_length;
|
||||
pfx_special.fp_addr.ip4.as_u32 = address->as_u32;
|
||||
|
||||
/* set the glean route for the prefix */
|
||||
fib_table_entry_update_one_path (fib_index, &pfx_special,
|
||||
FIB_SOURCE_INTERFACE,
|
||||
(FIB_ENTRY_FLAG_CONNECTED |
|
||||
FIB_ENTRY_FLAG_ATTACHED),
|
||||
DPO_PROTO_IP4,
|
||||
/* No next-hop address */
|
||||
NULL,
|
||||
sw_if_index,
|
||||
/* invalid FIB index */
|
||||
~0,
|
||||
1,
|
||||
/* no out-label stack */
|
||||
NULL,
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
|
||||
/* set a drop route for the base address of the prefix */
|
||||
pfx_special.fp_len = 32;
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
@@ -528,90 +528,52 @@ ip4_del_interface_prefix_routes (ip4_main_t * im,
|
||||
if_prefix->ref_count -= 1;
|
||||
|
||||
/*
|
||||
* Routes need to be adjusted if:
|
||||
* - deleting last intf addr in prefix
|
||||
* - deleting intf addr used as default source address in glean adjacency
|
||||
* Routes need to be adjusted if deleting last intf addr in prefix
|
||||
*
|
||||
* We're done now otherwise
|
||||
*/
|
||||
if ((if_prefix->ref_count > 0) &&
|
||||
!pool_is_free_index (lm->if_address_pool, if_prefix->src_ia_index))
|
||||
if (if_prefix->ref_count > 0)
|
||||
return;
|
||||
|
||||
/* length <= 30, delete glean route, first address, last address */
|
||||
if (address_length <= 30)
|
||||
{
|
||||
/* Less work to do in FIB if we remove the covered /32s first */
|
||||
|
||||
/* remove glean route for prefix */
|
||||
pfx_special.fp_addr.ip4 = *address;
|
||||
pfx_special.fp_len = address_length;
|
||||
fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE);
|
||||
/* first address in prefix */
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
address->as_u32 & im->fib_masks[address_length];
|
||||
pfx_special.fp_len = 32;
|
||||
|
||||
/* if no more intf addresses in prefix, remove other special routes */
|
||||
if (!if_prefix->ref_count)
|
||||
{
|
||||
/* first address in prefix */
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
address->as_u32 & im->fib_masks[address_length];
|
||||
pfx_special.fp_len = 32;
|
||||
if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32)
|
||||
fib_table_entry_special_remove (fib_index,
|
||||
&pfx_special,
|
||||
FIB_SOURCE_INTERFACE);
|
||||
|
||||
if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32)
|
||||
fib_table_entry_special_remove (fib_index,
|
||||
&pfx_special,
|
||||
FIB_SOURCE_INTERFACE);
|
||||
/* prefix broadcast address */
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
address->as_u32 | ~im->fib_masks[address_length];
|
||||
pfx_special.fp_len = 32;
|
||||
|
||||
/* prefix broadcast address */
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
address->as_u32 | ~im->fib_masks[address_length];
|
||||
pfx_special.fp_len = 32;
|
||||
|
||||
if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32)
|
||||
fib_table_entry_special_remove (fib_index,
|
||||
&pfx_special,
|
||||
FIB_SOURCE_INTERFACE);
|
||||
}
|
||||
else
|
||||
/* default source addr just got deleted, find another */
|
||||
{
|
||||
ip_interface_address_t *new_src_ia = NULL;
|
||||
ip4_address_t *new_src_addr = NULL;
|
||||
|
||||
new_src_addr =
|
||||
ip4_interface_address_matching_destination
|
||||
(im, address, sw_if_index, &new_src_ia);
|
||||
|
||||
if_prefix->src_ia_index = new_src_ia - lm->if_address_pool;
|
||||
|
||||
pfx_special.fp_len = address_length;
|
||||
pfx_special.fp_addr.ip4 = *new_src_addr;
|
||||
|
||||
/* set new glean route for the prefix */
|
||||
fib_table_entry_update_one_path (fib_index, &pfx_special,
|
||||
FIB_SOURCE_INTERFACE,
|
||||
(FIB_ENTRY_FLAG_CONNECTED |
|
||||
FIB_ENTRY_FLAG_ATTACHED),
|
||||
DPO_PROTO_IP4,
|
||||
/* No next-hop address */
|
||||
NULL,
|
||||
sw_if_index,
|
||||
/* invalid FIB index */
|
||||
~0,
|
||||
1,
|
||||
/* no out-label stack */
|
||||
NULL,
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
return;
|
||||
}
|
||||
if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32)
|
||||
fib_table_entry_special_remove (fib_index,
|
||||
&pfx_special,
|
||||
FIB_SOURCE_INTERFACE);
|
||||
}
|
||||
/* length == 31, delete attached route for the other address */
|
||||
else if (address_length == 31)
|
||||
{
|
||||
/* length == 31, delete attached route for the other address */
|
||||
pfx_special.fp_addr.ip4.as_u32 =
|
||||
address->as_u32 ^ clib_host_to_net_u32(1);
|
||||
|
||||
fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE);
|
||||
}
|
||||
|
||||
/* remove glean route for prefix */
|
||||
pfx_special.fp_addr.ip4 = *address;
|
||||
pfx_special.fp_len = address_length;
|
||||
fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE);
|
||||
|
||||
mhash_unset (&lm->prefix_to_if_prefix_index, &key, 0 /* old_value */);
|
||||
pool_put (lm->if_prefix_pool, if_prefix);
|
||||
}
|
||||
@@ -623,16 +585,15 @@ ip4_del_interface_routes (u32 sw_if_index,
|
||||
ip4_address_t * address, u32 address_length)
|
||||
{
|
||||
fib_prefix_t pfx = {
|
||||
.fp_len = address_length,
|
||||
.fp_len = 32,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
.fp_addr.ip4 = *address,
|
||||
};
|
||||
|
||||
fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
|
||||
|
||||
ip4_del_interface_prefix_routes (im, sw_if_index, fib_index,
|
||||
address, address_length);
|
||||
|
||||
pfx.fp_len = 32;
|
||||
fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
|
||||
}
|
||||
|
||||
#ifndef CLIB_MARCH_VARIANT
|
||||
@@ -2540,9 +2501,8 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm,
|
||||
thread_index, 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 */
|
||||
|
||||
@@ -336,41 +336,6 @@ ip6_link_get_mcast_adj (u32 sw_if_index)
|
||||
return (il->il_mcast_adj);
|
||||
}
|
||||
|
||||
int
|
||||
ip6_src_address_for_packet (u32 sw_if_index,
|
||||
const ip6_address_t * dst, ip6_address_t * src)
|
||||
{
|
||||
ip_lookup_main_t *lm;
|
||||
|
||||
lm = &ip6_main.lookup_main;
|
||||
|
||||
if (ip6_address_is_link_local_unicast (dst))
|
||||
{
|
||||
ip6_address_copy (src, ip6_get_link_local_address (sw_if_index));
|
||||
|
||||
return (!0);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 if_add_index =
|
||||
lm->if_address_pool_index_by_sw_if_index[sw_if_index];
|
||||
if (PREDICT_TRUE (if_add_index != ~0))
|
||||
{
|
||||
ip_interface_address_t *if_add =
|
||||
pool_elt_at_index (lm->if_address_pool, if_add_index);
|
||||
ip6_address_t *if_ip =
|
||||
ip_interface_address_get_address (lm, if_add);
|
||||
*src = *if_ip;
|
||||
return (!0);
|
||||
}
|
||||
}
|
||||
|
||||
src->as_u64[0] = 0;
|
||||
src->as_u64[1] = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ip6_link_set_local_address (u32 sw_if_index, const ip6_address_t * address)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user