diff options
Diffstat (limited to 'vnet')
-rw-r--r-- | vnet/vnet/lisp-cp/control.c | 97 | ||||
-rw-r--r-- | vnet/vnet/lisp-cp/lisp_types.c | 77 | ||||
-rw-r--r-- | vnet/vnet/lisp-cp/lisp_types.h | 2 |
3 files changed, 112 insertions, 64 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index fb4c8397d2d..f966b3645de 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -795,7 +795,8 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action, vnet_lisp_add_del_locator_set (ls_args, 0); /* return old mapping index */ - res_map_index[0] = mi; + if (res_map_index) + res_map_index[0] = mi; } /* success */ @@ -924,11 +925,10 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, unformat_input_t _line_input, * line_input = &_line_input; u8 is_add = 1, del_all = 0; locator_t rloc, * rlocs = 0, * curr_rloc = 0; - ip_prefix_t * deid_ippref, * seid_ippref; - gid_address_t seid, deid; - u8 * dmac = gid_address_mac (&deid); - u8 * smac = gid_address_mac (&seid); - u8 deid_set = 0, seid_set = 0; + ip_prefix_t * eid_ippref; + gid_address_t eid; + u8 * dmac = gid_address_mac (&eid); + u8 eid_set = 0; u8 * s = 0; u32 vni, action = ~0, p, w; int rv; @@ -937,12 +937,10 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, if (! unformat_user (input, unformat_line_input, line_input)) return 0; - memset(&deid, 0, sizeof(deid)); - memset(&seid, 0, sizeof(seid)); + memset(&eid, 0, sizeof(eid)); memset(&rloc, 0, sizeof(rloc)); - seid_ippref = &gid_address_ippref(&seid); - deid_ippref = &gid_address_ippref(&deid); + eid_ippref = &gid_address_ippref(&eid); while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -952,34 +950,21 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, is_add = 0; else if (unformat (line_input, "add")) ; - else if (unformat (line_input, "deid %U", - unformat_ip_prefix, deid_ippref)) + else if (unformat (line_input, "eid %U", + unformat_ip_prefix, eid_ippref)) { - gid_address_type (&deid) = GID_ADDR_IP_PREFIX; - deid_set = 1; + gid_address_type (&eid) = GID_ADDR_IP_PREFIX; + eid_set = 1; } - else if (unformat (line_input, "deid %U", + else if (unformat (line_input, "eid %U", unformat_mac_address, dmac)) { - gid_address_type (&deid) = GID_ADDR_MAC; - deid_set = 1; + gid_address_type (&eid) = GID_ADDR_MAC; + eid_set = 1; } else if (unformat (line_input, "vni %u", &vni)) { - gid_address_vni (&seid) = vni; - gid_address_vni (&deid) = vni; - } - else if (unformat (line_input, "seid %U", - unformat_ip_prefix, seid_ippref)) - { - gid_address_type (&seid) = GID_ADDR_IP_PREFIX; - seid_set = 1; - } - else if (unformat (line_input, "seid %U", - unformat_mac_address, smac)) - { - gid_address_type (&seid) = GID_ADDR_MAC; - seid_set = 1; + gid_address_vni (&eid) = vni; } else if (unformat (line_input, "p %d w %d", &p, &w)) { @@ -1020,31 +1005,15 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, } } - if (!del_all) + if (!eid_set) { - if (!deid_set) - { - clib_warning ("missing deid!"); - goto done; - } + clib_warning ("missing eid!"); + goto done; + } - if (GID_ADDR_IP_PREFIX == gid_address_type (&deid)) - { - /* if seid not set, make sure the ip version is the same as that - * of the deid. This ensures the seid to be configured will be - * either 0/0 or ::/0 */ - if (!seid_set) - ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref); + if (!del_all) + { - if (is_add && - (ip_prefix_version (deid_ippref) - != ip_prefix_version(seid_ippref))) - { - clib_warning ("source and destination EIDs are not" - " in the same IP family!"); - goto done; - } - } if (is_add && (~0 == action) && 0 == vec_len (rlocs)) @@ -1065,15 +1034,17 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, if (!is_add) { lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); - rv = lisp_add_del_adjacency (lcm, 0, &deid, /* is_add */ 0); - } - else - { - /* add as static remote mapping, i.e., not authoritative and infinite - * ttl */ - rv = vnet_lisp_add_del_mapping (&deid, rlocs, action, 0, ~0, is_add, 0); + rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0); + if (rv) + { + goto done; + } } + /* add as static remote mapping, i.e., not authoritative and infinite + * ttl */ + rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, 0); + if (rv) clib_warning("failed to %s remote mapping!", is_add ? "add" : "delete"); @@ -1087,8 +1058,8 @@ done: VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = { .path = "lisp remote-mapping", - .short_help = "lisp remote-mapping add|del [del-all] vni <vni>" - "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|" + .short_help = "lisp remote-mapping add|del [del-all] vni <vni> " + "eid <est-eid> [action <no-action|natively-forward|" "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]", .function = lisp_add_del_remote_mapping_command_fn, }; @@ -2441,6 +2412,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia); ip_address_set (rloc, addr, IP4); ip_prefix_len (ippref) = 32; + ip_prefix_normalize (ippref); vec_add1 (rlocs, gid[0]); })); @@ -2451,6 +2423,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia); ip_address_set (rloc, addr, IP6); ip_prefix_len (ippref) = 128; + ip_prefix_normalize (ippref); vec_add1 (rlocs, gid[0]); })); } diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c index c1c959c55a1..b5c7c3e964a 100644 --- a/vnet/vnet/lisp-cp/lisp_types.c +++ b/vnet/vnet/lisp-cp/lisp_types.c @@ -146,8 +146,20 @@ uword unformat_ip_prefix (unformat_input_t * input, va_list * args) { ip_prefix_t * a = va_arg(*args, ip_prefix_t *); - return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a), - &ip_prefix_len(a)); + if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a), + &ip_prefix_len(a))) + { + if ((ip_prefix_version(a) == IP4 && 32 < ip_prefix_len(a)) || + (ip_prefix_version(a) == IP6 && 128 < ip_prefix_length(a))) + { + clib_warning("Prefix length to big: %d!", ip_prefix_len(a)); + return 0; + } + ip_prefix_normalize(a); + } + else + return 0; + return 1; } uword @@ -511,6 +523,63 @@ ip_address_set(ip_address_t * dst, void * src, u8 version) ip_addr_version(dst) = version; } +void +ip_prefix_normalize(ip_prefix_t * a) +{ + ip_address_t * ip; + ip4_address_t * ip4; + ip6_address_t * ip6; + int preflen = ip_prefix_len(a); + u32 mask = ~0; + u64 mask_6[2]; + u32 * m; + u32 j, i0, i1; + + ip = &ip_prefix_addr (a); + switch (ip_addr_version (ip)) + { + case IP4: + if (32 <= preflen) + { + break; + } + + ip4 = &ip_addr_v4 (ip); + mask = pow2_mask (preflen) << (32 - preflen); + mask = clib_host_to_net_u32 (mask); + ip4->data_u32 &= mask; + break; + + case IP6: + if (128 <= preflen) + { + break; + } + ip6 = &ip_addr_v6 (ip); + memset(mask_6, 0, sizeof(mask_6)); + m = (u32 * ) mask_6; + + i0 = preflen / 32; + i1 = preflen % 32; + for (j = 0; j < i0; j++) + { + m[j] = ~0; + } + + if (i1) + { + m[i0] = clib_host_to_net_u32 (pow2_mask(i1) << (32 - i1)); + } + + ip6->as_u64[0] &= mask_6[0]; + ip6->as_u64[1] &= mask_6[1]; + break; + + default: + ASSERT(0); + } +} + void * ip_prefix_cast (gid_address_t * a) { @@ -564,6 +633,10 @@ int ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2) { int cmp = 0; + + ip_prefix_normalize (p1); + ip_prefix_normalize (p2); + cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2)); if (cmp == 0) { diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h index ef86f71bdf3..e3a0eb799b5 100644 --- a/vnet/vnet/lisp-cp/lisp_types.h +++ b/vnet/vnet/lisp-cp/lisp_types.h @@ -57,6 +57,8 @@ typedef CLIB_PACKED(struct ip_prefix #define ip_prefix_v4(_a) ip_addr_v4(&ip_prefix_addr(_a)) #define ip_prefix_v6(_a) ip_addr_v6(&ip_prefix_addr(_a)) +void ip_prefix_normalize(ip_prefix_t * a); + typedef enum { /* NOTE: ip addresses are left out on purpose. Use max masked ip-prefixes |