#define MAP_SKIP_IP6_LOOKUP 1
-typedef enum
-{
- MAP_SENDER,
- MAP_RECEIVER
-} map_dir_e;
-
int map_create_domain (ip4_address_t * ip4_prefix, u8 ip4_prefix_len,
ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
ip6_address_t * ip6_src, u8 ip6_src_len,
int map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep,
u8 is_add);
u8 *format_map_trace (u8 * s, va_list * args);
-i32 ip4_get_port (ip4_header_t * ip, map_dir_e dir, u16 buffer_len);
-i32 ip6_get_port (ip6_header_t * ip6, map_dir_e dir, u16 buffer_len);
-u16 ip4_map_get_port (ip4_header_t * ip, map_dir_e dir);
-typedef enum __attribute__ ((__packed__))
+typedef enum
{
- MAP_DOMAIN_PREFIX = 1 << 0, MAP_DOMAIN_TRANSLATION = 1 << 1, // The domain uses MAP-T
-} map_domain_flags_e;
+ MAP_DOMAIN_PREFIX = 1 << 0,
+ MAP_DOMAIN_TRANSLATION = 1 << 1, // The domain uses MAP-T
+ MAP_DOMAIN_RFC6052 = 1 << 2,
+} __attribute__ ((__packed__)) map_domain_flags_e;
/**
* IP4 reassembly logic:
map_ip6_fragment_t fragments[MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY];
} map_ip6_reass_t;
+#ifdef MAP_SKIP_IP6_LOOKUP
+/**
+ * A pre-resolved next-hop
+ */
+typedef struct map_main_pre_resolved_t_
+{
+ /**
+ * Linkage into the FIB graph
+ */
+ fib_node_t node;
+
+ /**
+ * The FIB entry index of the next-hop
+ */
+ fib_node_index_t fei;
+
+ /**
+ * This object sibling index on the FIB entry's child dependency list
+ */
+ u32 sibling;
+
+ /**
+ * The Load-balance object index to use to forward
+ */
+ dpo_id_t dpo;
+} map_main_pre_resolved_t;
+
+/**
+ * Pre-resolved next hops for v4 and v6. Why these are global and not
+ * per-domain is beyond me.
+ */
+extern map_main_pre_resolved_t pre_resolved[FIB_PROTOCOL_MAX];
+#endif
+
typedef struct {
/* pool of MAP domains */
map_domain_t *domains;
vlib_combined_counter_main_t *domain_counters;
volatile u32 *counter_lock;
-#ifdef MAP_SKIP_IP6_LOOKUP
- /* pre-presolve */
- u32 adj6_index, adj4_index;
- ip4_address_t preresolve_ip4;
- ip6_address_t preresolve_ip6;
-#endif
-
/* Traffic class: zero, copy (~0) or fixed value */
u8 tc;
bool tc_copy;
bool sec_check_frag; /* Inbound security check for (subsequent) fragments */
bool icmp6_enabled; /* Send destination unreachable for security check failure */
+ bool is_ce; /* If this MAP node is a Customer Edge router*/
+
/* ICMPv6 -> ICMPv4 relay parameters */
ip4_address_t icmp4_src_address;
vlib_simple_counter_main_t icmp_relayed;
u16 port;
} map_trace_t;
-map_main_t map_main;
+extern map_main_t map_main;
extern vlib_node_registration_t ip4_map_node;
extern vlib_node_registration_t ip6_map_node;
if (d->ip6_prefix_len == 128)
return clib_net_to_host_u64(d->ip6_prefix.as_u64[1]);
+ if (d->flags & MAP_DOMAIN_RFC6052)
+ return (clib_net_to_host_u64(d->ip6_prefix.as_u64[1]) | addr);
+
/* IPv4 prefix */
if (d->flags & MAP_DOMAIN_PREFIX)
return (u64) (addr & (0xFFFFFFFF << d->suffix_shift)) << 16;
}
static_always_inline u32
-map_get_ip4 (ip6_address_t *addr)
+map_get_ip4 (ip6_address_t *addr, map_domain_flags_e flags)
{
- return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1]) >> 16);
+ if (flags & MAP_DOMAIN_RFC6052)
+ return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1]));
+ else
+ return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1]) >> 16);
}
/*
* Get the MAP domain from an IPv4 lookup adjacency.
*/
static_always_inline map_domain_t *
-ip4_map_get_domain (u32 mdi,
- u32 *map_domain_index)
+ip4_map_get_domain (u32 mdi)
{
map_main_t *mm = &map_main;
- map_dpo_t *md;
-
- md = map_dpo_get(mdi);
- ASSERT(md);
- *map_domain_index = md->md_domain;
- return pool_elt_at_index(mm->domains, *map_domain_index);
+ return pool_elt_at_index(mm->domains, mdi);
}
/*
* The IPv4 address is used otherwise.
*/
static_always_inline map_domain_t *
-ip6_map_get_domain (u32 mdi, ip4_address_t *addr,
- u32 *map_domain_index, u8 *error)
+ip6_map_get_domain (u32 mdi,
+ ip4_address_t *addr,
+ u32 *map_domain_index,
+ u8 *error)
{
map_main_t *mm = &map_main;
- map_dpo_t *md;
+#ifdef TODO
/*
* Disable direct MAP domain lookup on decap, until the security check is updated to verify IPv4 SA.
* (That's done implicitly when MAP domain is looked up in the IPv4 FIB)
*/
-#ifdef MAP_NONSHARED_DOMAIN_ENABLED
- md = map_dpo_get(mdi);
-
- ASSERT(md);
- *map_domain_index = md->md_domain;
- if (*map_domain_index != ~0)
- return pool_elt_at_index(mm->domains, *map_domain_index);
+ //#ifdef MAP_NONSHARED_DOMAIN_ENABLED
+ //#error "How can you be sure this domain is not shared?"
#endif
+ *map_domain_index = mdi;
+ return pool_elt_at_index(mm->domains, mdi);
+
+#ifdef TODO
u32 lbi = ip4_fib_forwarding_lookup(0, addr);
const dpo_id_t *dpo = load_balance_get_bucket(lbi, 0);
if (PREDICT_TRUE(dpo->dpoi_type == map_dpo_type ||
dpo->dpoi_type == map_t_dpo_type))
{
- md = map_dpo_get(dpo->dpoi_index);
- *map_domain_index = md->md_domain;
+ *map_domain_index = dpo->dpoi_index;
return pool_elt_at_index(mm->domains, *map_domain_index);
}
*error = MAP_ERROR_NO_DOMAIN;
return NULL;
+#endif
}
map_ip4_reass_t *
int map_ip6_reass_conf_buffers(u32 buffers);
#define MAP_IP6_REASS_CONF_BUFFERS_MAX (0xffffffff)
-static_always_inline
-int ip6_parse(const ip6_header_t *ip6, u32 buff_len,
- u8 *l4_protocol, u16 *l4_offset, u16 *frag_hdr_offset)
-{
- if (ip6->protocol == IP_PROTOCOL_IPV6_FRAGMENTATION) {
- *l4_protocol = ((ip6_frag_hdr_t *)(ip6 + 1))->next_hdr;
- *frag_hdr_offset = sizeof(*ip6);
- *l4_offset = sizeof(*ip6) + sizeof(ip6_frag_hdr_t);
- } else {
- *l4_protocol = ip6->protocol;
- *frag_hdr_offset = 0;
- *l4_offset = sizeof(*ip6);
- }
-
- return (buff_len < (*l4_offset + 4)) ||
- (clib_net_to_host_u16(ip6->payload_length) < (*l4_offset + 4 - sizeof(*ip6)));
-}
-
-
-#define u8_ptr_add(ptr, index) (((u8 *)ptr) + index)
-#define u16_net_add(u, val) clib_host_to_net_u16(clib_net_to_host_u16(u) + (val))
-
-#define frag_id_6to4(id) ((id) ^ ((id) >> 16))
-
static_always_inline void
ip4_map_t_embedded_address (map_domain_t *d,
ip6_address_t *ip6, const ip4_address_t *ip4)