X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Fsr%2Fsr.c;h=e17b474e9e7eafec18197b19742d11d805853af7;hb=52fc44d61bcebb898dc19ab818ff60e617055694;hp=699df992d15572d3eefa5d3e2d31265a6f0b3486;hpb=6de2ff28fef27421f6b9a6c1f4ef53d1bd8c7c6e;p=vpp.git diff --git a/vnet/vnet/sr/sr.c b/vnet/vnet/sr/sr.c index 699df992d15..e17b474e9e7 100644 --- a/vnet/vnet/sr/sr.c +++ b/vnet/vnet/sr/sr.c @@ -23,7 +23,7 @@ ip6_sr_main_t sr_main; static vlib_node_registration_t sr_local_node; -static void sr_fix_hmac (ip6_sr_main_t * sm, ip6_header_t * ip, +void sr_fix_hmac (ip6_sr_main_t * sm, ip6_header_t * ip, ip6_sr_header_t * sr) { u32 key_index; @@ -204,7 +204,8 @@ u8 * format_ip6_sr_header_with_length (u8 * s, va_list * args) #define foreach_sr_rewrite_next \ _(ERROR, "error-drop") \ _(IP6_LOOKUP, "ip6-lookup") \ -_(SR_LOCAL, "sr-local") +_(SR_LOCAL, "sr-local") \ +_(SR_REPLICATE,"sr-replicate") typedef enum { #define _(s,n) SR_REWRITE_NEXT_##s, @@ -289,7 +290,8 @@ sr_rewrite (vlib_main_t * vm, vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from >= 4 && n_left_to_next >= 2) + /* Note 2x loop disabled */ + while (0 && n_left_from >= 4 && n_left_to_next >= 2) { u32 bi0, bi1; vlib_buffer_t * b0, * b1; @@ -301,7 +303,8 @@ sr_rewrite (vlib_main_t * vm, u64 * copy_src1, * copy_dst1; u32 next0 = SR_REWRITE_NEXT_IP6_LOOKUP; u32 next1 = SR_REWRITE_NEXT_IP6_LOOKUP; - u16 new_l0, new_l1; + u16 new_l0 = 0; + u16 new_l1 = 0; /* Prefetch next iteration. */ { @@ -490,13 +493,13 @@ sr_rewrite (vlib_main_t * vm, { u32 bi0; vlib_buffer_t * b0; - ip6_header_t * ip0; + ip6_header_t * ip0 = 0; ip_adjacency_t * adj0; - ip6_sr_header_t * sr0; + ip6_sr_header_t * sr0 = 0; ip6_sr_tunnel_t * t0; u64 * copy_src0, * copy_dst0; u32 next0 = SR_REWRITE_NEXT_IP6_LOOKUP; - u16 new_l0; + u16 new_l0 = 0; bi0 = from[0]; to_next[0] = bi0; @@ -516,6 +519,14 @@ sr_rewrite (vlib_main_t * vm, t0 = pool_elt_at_index (sm->tunnels, adj0->rewrite_header.sw_if_index); + /* add a replication node */ + if(PREDICT_FALSE(t0->policy_index != ~0)) + { + vnet_buffer(b0)->ip.save_protocol = t0->policy_index; + next0=SR_REWRITE_NEXT_SR_REPLICATE; + goto trace0; + } + ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >= ((word) vec_len (t0->rewrite)) + b0->current_data); @@ -582,15 +593,19 @@ sr_rewrite (vlib_main_t * vm, } } + trace0: if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { sr_rewrite_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_index = t0 - sm->tunnels; - clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, + if (ip0) + { + memcpy (tr->src.as_u8, ip0->src_address.as_u8, sizeof (tr->src.as_u8)); - clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, + memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, sizeof (tr->dst.as_u8)); + } tr->length = new_l0; tr->next_index = next0; clib_memcpy (tr->sr, sr0, sizeof (tr->sr)); @@ -715,6 +730,7 @@ find_or_add_shared_secret (ip6_sr_main_t * sm, u8 * secret, u32 * indexp) return (key); } + int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) { ip6_main_t * im = &ip6_main; @@ -733,6 +749,8 @@ int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) ip6_add_del_route_args_t aa; u32 hmac_key_index_u32; u8 hmac_key_index = 0; + ip6_sr_policy_t * pt; + int i; /* Make sure that the rx FIB exists */ p = hash_get (im->fib_index_by_table_id, a->rx_table_id); @@ -755,7 +773,11 @@ int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) clib_memcpy (key.src.as_u8, a->src_address->as_u8, sizeof (key.src)); clib_memcpy (key.dst.as_u8, a->dst_address->as_u8, sizeof (key.dst)); - p = hash_get_mem (sm->tunnel_index_by_key, &key); + /* If the name exists, find the tunnel by name else... */ + if (a->name) + p = hash_get_mem(sm->tunnel_index_by_name, a->name); + else if (p==0) + p = hash_get_mem (sm->tunnel_index_by_key, &key); if (p) { @@ -769,6 +791,36 @@ int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) ip6_delete_route_no_next_hop (&t->key.dst, t->dst_mask_width, a->rx_table_id); vec_free (t->rewrite); + /* Remove tunnel from any policy if associated */ + if (t->policy_index != ~0) + { + pt=pool_elt_at_index (sm->policies, t->policy_index); + for (i=0; i< vec_len (pt->tunnel_indices); i++) + { + if (pt->tunnel_indices[i] == t - sm->tunnels) + { + vec_delete (pt->tunnel_indices, 1, i); + goto found; + } + } + clib_warning ("Tunnel index %d not found in policy_index %d", + t - sm->tunnels, pt - sm->policies); + found: + /* If this is last tunnel in the policy, clean up the policy too */ + if (vec_len (pt->tunnel_indices) == 0) + { + hash_unset_mem (sm->policy_index_by_policy_name, pt->name); + vec_free (pt->name); + pool_put (sm->policies, pt); + } + } + + /* Clean up the tunnel by name */ + if (t->name) + { + hash_unset_mem (sm->tunnel_index_by_name, t->name); + vec_free (t->name); + } pool_put (sm->tunnels, t); hp = hash_get_pair (sm->tunnel_index_by_key, &key); key_copy = (void *)(hp->key); @@ -789,6 +841,7 @@ int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) /* create a new tunnel */ pool_get (sm->tunnels, t); memset (t, 0, sizeof (*t)); + t->policy_index = ~0; clib_memcpy (&t->key, &key, sizeof (t->key)); t->dst_mask_width = a->dst_mask_width; @@ -902,6 +955,31 @@ int ip6_sr_add_del_tunnel (ip6_sr_add_del_tunnel_args_t * a) ip6_add_del_route (im, &aa); vec_free (add_adj); + if (a->policy_name) + { + p=hash_get_mem (sm->policy_index_by_policy_name, a->policy_name); + if (p) + { + pt = pool_elt_at_index (sm->policies, p[0]); + } + else /* no policy, lets create one */ + { + pool_get (sm->policies, pt); + memset (pt, 0, sizeof(*pt)); + pt->name = format (0, "%s%c", a->policy_name, 0); + hash_set_mem (sm->policy_index_by_policy_name, pt->name, pt - sm->policies); + p=hash_get_mem (sm->policy_index_by_policy_name, a->policy_name); + } + vec_add1 (pt->tunnel_indices, t - sm->tunnels); + t->policy_index = p[0]; /* equiv. to (pt - sm->policies) */ + } + + if (a->name) + { + t->name = format (0, "%s%c", a->name, 0); + hash_set_mem(sm->tunnel_index_by_name, t->name, t - sm->tunnels); + } + return 0; } @@ -918,6 +996,8 @@ sr_add_del_tunnel_command_fn (vlib_main_t * vm, int dst_address_set = 0; u16 flags = 0; u8 *shared_secret = 0; + u8 *name = 0; + u8 *policy_name = 0; u32 rx_table_id = 0; u32 tx_table_id = 0; ip6_address_t * segments = 0; @@ -939,6 +1019,10 @@ sr_add_del_tunnel_command_fn (vlib_main_t * vm, ; else if (unformat (input, "src %U", unformat_ip6_address, &src_address)) src_address_set = 1; + else if (unformat (input, "name %s", &name)) + ; + else if (unformat (input, "policy %s", &policy_name)) + ; else if (unformat (input, "dst %U/%d", unformat_ip6_address, &dst_address, &dst_mask_width)) @@ -1013,6 +1097,16 @@ sr_add_del_tunnel_command_fn (vlib_main_t * vm, a->tx_table_id = tx_table_id; a->shared_secret = shared_secret; + if (vec_len(name)) + a->name = name; + else + a->name = 0; + + if (vec_len(policy_name)) + a->policy_name = policy_name; + else + a->policy_name = 0; + rv = ip6_sr_add_del_tunnel (a); vec_free (segments); @@ -1051,10 +1145,46 @@ sr_add_del_tunnel_command_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (sr_tunnel_command, static) = { .path = "sr tunnel", .short_help = - "sr tunnel [del] [next ] [cleanup] [reroute] [key %s]", + "sr tunnel [del] [name ] src dst [next ] [cleanup] [reroute] [key %s] [policy ", .function = sr_add_del_tunnel_command_fn, }; +void +ip6_sr_tunnel_display (vlib_main_t * vm, + ip6_sr_tunnel_t * t) +{ + ip6_main_t * im = &ip6_main; + ip6_sr_main_t * sm = &sr_main; + ip6_fib_t * rx_fib, * tx_fib; + ip6_sr_policy_t * pt; + + rx_fib = find_ip6_fib_by_table_index_or_id (im, t->rx_fib_index, + IP6_ROUTE_FLAG_FIB_INDEX); + + tx_fib = find_ip6_fib_by_table_index_or_id (im, t->tx_fib_index, + IP6_ROUTE_FLAG_FIB_INDEX); + + if (t->name) + vlib_cli_output (vm,"sr tunnel name: %s", (char *)t->name); + + vlib_cli_output (vm, "src %U dst %U first hop %U", + format_ip6_address, &t->key.src, + format_ip6_address, &t->key.dst, + format_ip6_address, &t->first_hop); + vlib_cli_output (vm, " rx-fib-id %d tx-fib-id %d", + rx_fib->table_id, tx_fib->table_id); + vlib_cli_output (vm, " sr: %U", format_ip6_sr_header, t->rewrite, + 0 /* print_hmac */); + + if (t->policy_index != ~0) + { + pt=pool_elt_at_index(sm->policies, t->policy_index); + vlib_cli_output (vm,"sr policy: %s", (char *)pt->name); + } + vlib_cli_output (vm, "-------"); + + return; +} static clib_error_t * show_sr_tunnel_fn (vlib_main_t * vm, @@ -1064,39 +1194,41 @@ show_sr_tunnel_fn (vlib_main_t * vm, static ip6_sr_tunnel_t ** tunnels; ip6_sr_tunnel_t * t; ip6_sr_main_t * sm = &sr_main; - ip6_main_t * im = &ip6_main; - ip6_fib_t * rx_fib, * tx_fib; int i; + uword * p = 0; + u8 *name = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "name %s", &name)) + { + p=hash_get_mem (sm->tunnel_index_by_name, name); + if(!p) + vlib_cli_output (vm, "No SR tunnel with name: %s. Showing all.", name); + } + else + break; + } vec_reset_length (tunnels); + if(!p) /* Either name parm not passed or no tunnel with that name found, show all */ + { pool_foreach (t, sm->tunnels, ({ vec_add1 (tunnels, t); })); + } + else /* Just show the one tunnel by name */ + vec_add1 (tunnels, &sm->tunnels[p[0]]); if (vec_len (tunnels) == 0) vlib_cli_output (vm, "No SR tunnels configured"); for (i = 0; i < vec_len (tunnels); i++) { - t = tunnels [i]; - - rx_fib = find_ip6_fib_by_table_index_or_id (im, t->rx_fib_index, - IP6_ROUTE_FLAG_FIB_INDEX); - - tx_fib = find_ip6_fib_by_table_index_or_id (im, t->tx_fib_index, - IP6_ROUTE_FLAG_FIB_INDEX); - - vlib_cli_output (vm, "src %U dst %U first hop %U", - format_ip6_address, &t->key.src, - format_ip6_address, &t->key.dst, - format_ip6_address, &t->first_hop); - vlib_cli_output (vm, " rx-fib-id %d tx-fib-id %d", - rx_fib->table_id, tx_fib->table_id); - vlib_cli_output (vm, " sr: %U", format_ip6_sr_header, t->rewrite, - 0 /* print_hmac */); - vlib_cli_output (vm, "-------"); + t = tunnels[i]; + ip6_sr_tunnel_display (vm, t); } return 0; @@ -1104,10 +1236,434 @@ show_sr_tunnel_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (show_sr_tunnel_command, static) = { .path = "show sr tunnel", - .short_help = "show sr tunnel", + .short_help = "show sr tunnel [name ]", .function = show_sr_tunnel_fn, }; +int ip6_sr_add_del_policy (ip6_sr_add_del_policy_args_t * a) +{ + ip6_sr_main_t * sm = &sr_main; + uword * p; + ip6_sr_tunnel_t * t = 0; + ip6_sr_policy_t * policy; + u32 * tunnel_indices = 0; + int i; + + + + if (a->is_del) + { + p=hash_get_mem (sm->policy_index_by_policy_name, a->name); + if (!p) + return -6; /* policy name not found */ + + policy = pool_elt_at_index(sm->policies, p[0]); + + vec_foreach_index (i, policy->tunnel_indices) + { + t = pool_elt_at_index (sm->tunnels, policy->tunnel_indices[i]); + t->policy_index = ~0; + } + hash_unset_mem (sm->policy_index_by_policy_name, a->name); + pool_put (sm->policies, policy); + return 0; + } + + + if (!vec_len(a->tunnel_names)) + return -3; /*tunnel name is required case */ + + vec_reset_length (tunnel_indices); + /* Check tunnel names, add tunnel_index to policy */ + for (i=0; i < vec_len (a->tunnel_names); i++) + { + p = hash_get_mem (sm->tunnel_index_by_name, a->tunnel_names[i]); + if (!p) + return -4; /* tunnel name not found case */ + + t = pool_elt_at_index (sm->tunnels, p[0]); + /* + No need to check t==0. -3 condition above ensures name + */ + if (t->policy_index != ~0) + return -5; /* tunnel name already associated with a policy */ + + /* Add to tunnel indicies */ + vec_add1 (tunnel_indices, p[0]); + } + + /* Add policy to ip6_sr_main_t */ + pool_get (sm->policies, policy); + policy->name = a->name; + policy->tunnel_indices = tunnel_indices; + hash_set_mem (sm->policy_index_by_policy_name, policy->name, policy - sm->policies); + + /* Yes, this could be construed as overkill but the last thing you should do is set + the policy_index on the tunnel after everything is set in ip6_sr_main_t. + If this is deemed overly cautious, could set this in the vec_len(tunnel_names) loop. + */ + for (i=0; i < vec_len(policy->tunnel_indices); i++) + { + t = pool_elt_at_index (sm->tunnels, policy->tunnel_indices[i]); + t->policy_index = policy - sm->policies; + } + + return 0; +} + + +static clib_error_t * +sr_add_del_policy_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + int is_del = 0; + u8 ** tunnel_names = 0; + u8 * tunnel_name = 0; + u8 * name = 0; + ip6_sr_add_del_policy_args_t _a, *a=&_a; + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_del = 1; + else if (unformat (input, "name %s", &name)) + ; + else if (unformat (input, "tunnel %s", &tunnel_name)) + { + if (tunnel_name) + { + vec_add1 (tunnel_names, tunnel_name); + tunnel_name = 0; + } + } + else + break; + } + + if (!name) + return clib_error_return (0, "name of SR policy required"); + + + memset(a, 0, sizeof(*a)); + + a->is_del = is_del; + a->name = name; + a->tunnel_names = tunnel_names; + + rv = ip6_sr_add_del_policy (a); + + vec_free(tunnel_names); + + switch (rv) + { + case 0: + break; + + case -3: + return clib_error_return (0, "tunnel name to associate to SR policy is required"); + + case -4: + return clib_error_return (0, "tunnel name not found"); + + case -5: + return clib_error_return (0, "tunnel already associated with policy"); + + case -6: + return clib_error_return (0, "policy name %s not found", name); + + case -7: + return clib_error_return (0, "TODO: deleting policy name %s", name); + + default: + return clib_error_return (0, "BUG: ip6_sr_add_del_policy returns %d", rv); + + } + return 0; +} + +VLIB_CLI_COMMAND (sr_policy_command, static) = { + .path = "sr policy", + .short_help = + "sr policy [del] name tunnel [tunnel ]*", + .function = sr_add_del_policy_command_fn, +}; + +static clib_error_t * +show_sr_policy_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + static ip6_sr_policy_t ** policies; + ip6_sr_policy_t * policy; + ip6_sr_tunnel_t * t; + ip6_sr_main_t * sm = &sr_main; + int i, j; + uword * p = 0; + u8 * name = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "name %s", &name)) + { + p=hash_get_mem (sm->policy_index_by_policy_name, name); + if(!p) + vlib_cli_output (vm, "policy with name %s not found. Showing all.", name); + } + else + break; + } + + vec_reset_length (policies); + + if(!p) /* Either name parm not passed or no policy with that name found, show all */ + { + pool_foreach (policy, sm->policies, + ({ + vec_add1 (policies, policy); + })); + } + else /* Just show the one policy by name and a summary of tunnel names */ + { + policy = pool_elt_at_index(sm->policies, p[0]); + vec_add1 (policies, policy); + } + + if (vec_len (policies) == 0) + vlib_cli_output (vm, "No SR policies configured"); + + for (i = 0; i < vec_len (policies); i++) + { + policy = policies [i]; + + if(policy->name) + vlib_cli_output (vm,"SR policy name: %s", (char *)policy->name); + for(j = 0; j < vec_len (policy->tunnel_indices); j++) + { + t = pool_elt_at_index (sm->tunnels, policy->tunnel_indices[j]); + ip6_sr_tunnel_display (vm, t); + } + } + + return 0; + +} + +VLIB_CLI_COMMAND (show_sr_policy_command, static) = { + .path = "show sr policy", + .short_help = "show sr policy [name ]", + .function = show_sr_policy_fn, +}; + +int ip6_sr_add_del_multicastmap (ip6_sr_add_del_multicastmap_args_t * a) +{ + uword * p; + ip6_main_t * im = &ip6_main; + ip_lookup_main_t * lm = &im->lookup_main; + ip6_sr_tunnel_t * t; + ip_adjacency_t adj, * ap, * add_adj = 0; + u32 adj_index; + ip6_sr_main_t * sm = &sr_main; + ip6_add_del_route_args_t aa; + ip6_sr_policy_t * pt; + + if (a->is_del) + { + /* clean up the adjacency */ + p = hash_get_mem (sm->policy_index_by_multicast_address, a->multicast_address); + } + else + { + /* Get our policy by policy_name */ + p = hash_get_mem (sm->policy_index_by_policy_name, a->policy_name); + + } + if (!p) + return -1; + + pt=pool_elt_at_index (sm->policies, p[0]); + + /* + Get the first tunnel associated with policy populate the fib adjacency. + From there, since this tunnel will have it's policy_index != ~0 it will + be the trigger in the dual_loop to pull up the policy and make a copy-rewrite + for each tunnel in the policy + */ + + t = pool_elt_at_index (sm->tunnels, pt->tunnel_indices[0]); + + /* Construct a FIB entry for multicast using the rx/tx fib from the first tunnel */ + memset(&adj, 0, sizeof (adj)); + + /* Create an adjacency and add to v6 fib */ + adj.lookup_next_index = sm->ip6_lookup_sr_replicate_index; + adj.explicit_fib_index = ~0; + + ap = ip_add_adjacency (lm, &adj, 1 /* one adj */, + &adj_index); + + /* + * Stick the tunnel index into the rewrite header. + * + * Unfortunately, inserting an SR header according to the various + * RFC's requires parsing through the ip6 header, perhaps consing a + * buffer onto the head of the vlib_buffer_t, etc. We don't use the + * normal reverse bcopy rewrite code. + * + * We don't handle ugly RFC-related cases yet, but I'm sure PL will complain + * at some point... + */ + ap->rewrite_header.sw_if_index = t - sm->tunnels; + + vec_add1 (add_adj, ap[0]); + + memcpy (aa.dst_address.as_u8, a->multicast_address, sizeof (aa.dst_address.as_u8)); + aa.dst_address_length = 128; + + aa.flags = (a->is_del ? IP6_ROUTE_FLAG_DEL : IP6_ROUTE_FLAG_ADD); + aa.flags |= IP6_ROUTE_FLAG_FIB_INDEX; + aa.table_index_or_table_id = t->rx_fib_index; + aa.add_adj = add_adj; + aa.adj_index = adj_index; + aa.n_add_adj = 1; + ip6_add_del_route (im, &aa); + vec_free (add_adj); + + u8 * mcast_copy = 0; + mcast_copy = vec_new (ip6_address_t, 1); + memcpy (mcast_copy, a->multicast_address, sizeof (ip6_address_t)); + + if (a->is_del) + { + hash_unset_mem (sm->policy_index_by_multicast_address, mcast_copy); + vec_free (mcast_copy); + return 0; + } + /* else */ + + hash_set_mem (sm->policy_index_by_multicast_address, mcast_copy, pt - sm->policies); + + + return 0; +} + +static clib_error_t * +sr_add_del_multicast_map_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + int is_del = 0; + ip6_address_t multicast_address; + u8 * policy_name = 0; + int multicast_address_set = 0; + ip6_sr_add_del_multicastmap_args_t _a, *a=&_a; + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_del = 1; + else if (unformat (input, "address %U", unformat_ip6_address, &multicast_address)) + multicast_address_set = 1; + else if (unformat (input, "sr-policy %s", &policy_name)) + ; + else + break; + } + + if (!is_del && !policy_name) + return clib_error_return (0, "name of sr policy required"); + + if (!multicast_address_set) + return clib_error_return (0, "multicast address required"); + + memset(a, 0, sizeof(*a)); + + a->is_del = is_del; + a->multicast_address = &multicast_address; + a->policy_name = policy_name; + + rv = ip6_sr_add_del_multicastmap (a); + + switch (rv) + { + case 0: + break; + case -1: + return clib_error_return (0, "no policy with name: %s", policy_name); + + case -2: + return clib_error_return (0, "multicast map someting "); + + case -3: + return clib_error_return (0, "tunnel name to associate to SR policy is required"); + + case -7: + return clib_error_return (0, "TODO: deleting policy name %s", policy_name); + + default: + return clib_error_return (0, "BUG: ip6_sr_add_del_policy returns %d", rv); + + } + return 0; + +} + + +VLIB_CLI_COMMAND (sr_multicast_map_command, static) = { + .path = "sr multicast-map", + .short_help = + "sr multicast-map address sr-policy [del]", + .function = sr_add_del_multicast_map_command_fn, +}; + +static clib_error_t * +show_sr_multicast_map_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + ip6_sr_main_t * sm = &sr_main; + u8 * key = 0; + u32 value; + ip6_address_t multicast_address; + ip6_sr_policy_t * pt ; + + /* pull all entries from the hash table into vector for display */ + + hash_foreach_mem (key, value, sm->policy_index_by_multicast_address, + ({ + if (!key) + vlib_cli_output (vm, "no multicast maps configured"); + else + { + multicast_address = *((ip6_address_t *)key); + pt = pool_elt_at_index (sm->policies, value); + if (pt) + { + vlib_cli_output (vm, "address: %U policy: %s", + format_ip6_address, &multicast_address, + pt->name); + } + else + vlib_cli_output (vm, "BUG: policy not found for address: %U with policy index %d", + format_ip6_address, &multicast_address, + value); + + } + + })); + + return 0; +} + +VLIB_CLI_COMMAND (show_sr_multicast_map_command, static) = { + .path = "show sr multicast-map", + .short_help = "show sr multicast-map", + .function = show_sr_multicast_map_fn, +}; + + #define foreach_sr_fix_dst_addr_next \ _(DROP, "error-drop") @@ -1363,6 +1919,15 @@ static clib_error_t * sr_init (vlib_main_t * vm) sm->tunnel_index_by_key = hash_create_mem (0, sizeof (ip6_sr_tunnel_key_t), sizeof (uword)); + sm->tunnel_index_by_name = + hash_create_string (0, sizeof (uword)); + + sm->policy_index_by_policy_name = + hash_create_string(0, sizeof (uword)); + + sm->policy_index_by_multicast_address = + hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword)); + sm->hmac_key_by_shared_secret = hash_create_string (0, sizeof(uword)); ip6_register_protocol (43, sr_local_node.index); @@ -1381,6 +1946,10 @@ static clib_error_t * sr_init (vlib_main_t * vm) sm->ip6_lookup_sr_next_index = vlib_node_add_next (vm, ip6_lookup_node->index, sr_rewrite_node.index); + /* Add a disposition to sr_replicate for the sr multicast replicate node */ + sm->ip6_lookup_sr_replicate_index = + vlib_node_add_next (vm, ip6_lookup_node->index, sr_replicate_node.index); + /* Add a disposition to ip6_rewrite for the sr dst address hack node */ sm->ip6_rewrite_sr_next_index = vlib_node_add_next (vm, ip6_rewrite_node->index, @@ -1824,7 +2393,7 @@ sr_local (vlib_main_t * vm, { u32 bi0; vlib_buffer_t * b0; - ip6_header_t * ip0; + ip6_header_t * ip0 = 0; ip6_sr_header_t * sr0; ip6_address_t * new_dst0; u32 next0 = SR_LOCAL_NEXT_IP6_LOOKUP;