diff options
Diffstat (limited to 'vnet/vnet/mpls/mpls.c')
-rw-r--r-- | vnet/vnet/mpls/mpls.c | 451 |
1 files changed, 123 insertions, 328 deletions
diff --git a/vnet/vnet/mpls/mpls.c b/vnet/vnet/mpls/mpls.c index aa1d963dca1..e6ae4980067 100644 --- a/vnet/vnet/mpls/mpls.c +++ b/vnet/vnet/mpls/mpls.c @@ -121,45 +121,6 @@ unformat_mpls_header (unformat_input_t * input, va_list * args) return 1; } -u8 * format_mpls_eth_tx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - mpls_eth_tx_trace_t * t = va_arg (*args, mpls_eth_tx_trace_t *); - mpls_main_t * mm = &mpls_main; - - if (t->lookup_miss) - s = format (s, "MPLS: lookup miss"); - else - { - s = format (s, "MPLS: tunnel %d labels %U len %d tx_sw_index %d dst %U", - t->tunnel_id, - format_mpls_encap_index, mm, t->mpls_encap_index, - clib_net_to_host_u16 (t->length), - t->tx_sw_if_index, - format_ethernet_address, t->dst); - } - return s; -} - -u8 * format_mpls_eth_header_with_length (u8 * s, va_list * args) -{ - ethernet_header_t * h = va_arg (*args, ethernet_header_t *); - mpls_unicast_header_t * m = (mpls_unicast_header_t *)(h+1); - u32 max_header_bytes = va_arg (*args, u32); - uword header_bytes; - - header_bytes = sizeof (h[0]); - if (max_header_bytes != 0 && header_bytes > max_header_bytes) - return format (s, "ethernet header truncated"); - - s = format - (s, "ETHERNET-MPLS label %d", - vnet_mpls_uc_get_label (clib_net_to_host_u32 (m->label_exp_s_ttl))); - - return s; -} - uword unformat_mpls_label_net_byte_order (unformat_input_t * input, va_list * args) @@ -176,157 +137,6 @@ unformat_mpls_label_net_byte_order (unformat_input_t * input, return 1; } -mpls_encap_t * -mpls_encap_by_fib_and_dest (mpls_main_t * mm, u32 rx_fib, u32 dst_address) -{ - uword * p; - mpls_encap_t * e; - u64 key; - - key = ((u64)rx_fib<<32) | ((u64) dst_address); - p = hash_get (mm->mpls_encap_by_fib_and_dest, key); - - if (!p) - return 0; - - e = pool_elt_at_index (mm->encaps, p[0]); - return e; -} - -int vnet_mpls_add_del_encap (ip4_address_t *dest, u32 fib_id, - u32 *labels_host_byte_order, - u32 policy_tunnel_index, - int no_dst_hash, u32 * indexp, int is_add) -{ - mpls_main_t * mm = &mpls_main; - ip4_main_t * im = &ip4_main; - mpls_encap_t * e; - u32 label_net_byte_order, label_host_byte_order; - u32 fib_index; - u64 key; - uword *p; - int i; - - p = hash_get (im->fib_index_by_table_id, fib_id); - if (! p) - return VNET_API_ERROR_NO_SUCH_FIB; - - fib_index = p[0]; - - key = ((u64)fib_index<<32) | ((u64) dest->as_u32); - - if (is_add) - { - pool_get (mm->encaps, e); - memset (e, 0, sizeof (*e)); - - for (i = 0; i < vec_len (labels_host_byte_order); i++) - { - mpls_unicast_header_t h; - label_host_byte_order = labels_host_byte_order[i]; - - /* Reformat label into mpls_unicast_header_t */ - label_host_byte_order <<= 12; - // FIXME NEOS AND EOS - //if (i == vec_len(labels_host_byte_order) - 1) - // label_host_byte_order |= 1<<8; /* S=1 */ - label_host_byte_order |= 0xff; /* TTL=FF */ - label_net_byte_order = clib_host_to_net_u32 (label_host_byte_order); - h.label_exp_s_ttl = label_net_byte_order; - vec_add1 (e->labels, h); - } - if (no_dst_hash == 0) - hash_set (mm->mpls_encap_by_fib_and_dest, key, e - mm->encaps); - if (indexp) - *indexp = e - mm->encaps; - if (policy_tunnel_index != ~0) - return vnet_mpls_policy_tunnel_add_rewrite (mm, e, policy_tunnel_index); - } - else - { - p = hash_get (mm->mpls_encap_by_fib_and_dest, key); - if (!p) - return VNET_API_ERROR_NO_SUCH_LABEL; - - e = pool_elt_at_index (mm->encaps, p[0]); - - vec_free (e->labels); - vec_free (e->rewrite); - pool_put(mm->encaps, e); - - if (no_dst_hash == 0) - hash_unset (mm->mpls_encap_by_fib_and_dest, key); - } - return 0; -} - -static clib_error_t * -mpls_add_encap_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u32 fib_id; - u32 *labels = 0; - u32 this_label; - ip4_address_t dest; - u32 policy_tunnel_index = ~0; - int no_dst_hash = 0; - int rv; - int fib_set = 0; - int dest_set = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "fib %d", &fib_id)) - fib_set = 1; - else if (unformat (input, "dest %U", unformat_ip4_address, &dest)) - dest_set = 1; - else if (unformat (input, "no-dst-hash")) - no_dst_hash = 1; - else if (unformat (input, "label %d", &this_label)) - vec_add1 (labels, this_label); - else if (unformat (input, "policy-tunnel %d", &policy_tunnel_index)) - ; - else - break; - } - - if (fib_set == 0) - return clib_error_return (0, "fib-id missing"); - if (dest_set == 0) - return clib_error_return (0, "destination IP address missing"); - if (vec_len (labels) == 0) - return clib_error_return (0, "label stack missing"); - - rv = vnet_mpls_add_del_encap (&dest, fib_id, labels, - policy_tunnel_index, - no_dst_hash, 0 /* indexp */, - 1 /* is_add */); - vec_free (labels); - - switch (rv) - { - case 0: - break; - - case VNET_API_ERROR_NO_SUCH_FIB: - return clib_error_return (0, "fib id %d unknown", fib_id); - - default: - return clib_error_return (0, "vnet_mpls_add_del_encap returned %d", - rv); - } - - return 0; -} - -VLIB_CLI_COMMAND (mpls_add_encap_command, static) = { - .path = "mpls encap add", - .short_help = - "mpls encap add label <label> ... fib <id> dest <ip4-address>", - .function = mpls_add_encap_command_fn, -}; - u8 * format_mpls_unicast_header_host_byte_order (u8 * s, va_list * args) { mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *); @@ -351,46 +161,6 @@ u8 * format_mpls_unicast_header_net_byte_order (u8 * s, va_list * args) &h_host); } -static clib_error_t * -mpls_del_encap_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u32 fib_id; - ip4_address_t dest; - int rv; - - if (unformat (input, "fib %d dest %U", &fib_id, - unformat_ip4_address, &dest)) - { - rv = vnet_mpls_add_del_encap (&dest, fib_id, 0 /* labels */, - ~0 /* policy_tunnel_index */, - 0 /* no_dst_hash */, - 0 /* indexp */, - 0 /* is_add */); - switch (rv) - { - case VNET_API_ERROR_NO_SUCH_FIB: - return clib_error_return (0, "fib id %d unknown", fib_id); - case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "dest %U not in fib %d", - format_ip4_address, &dest, fib_id); - default: - break; - } - return 0; - } - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); -} - -VLIB_CLI_COMMAND (mpls_del_encap_command, static) = { - .path = "mpls encap delete", - .short_help = "mpls encap delete fib <id> dest <ip4-address>", - .function = mpls_del_encap_command_fn, -}; - int mpls_dest_cmp(void * a1, void * a2) { @@ -419,65 +189,22 @@ mpls_label_cmp(void * a1, void * a2) } static clib_error_t * -show_mpls_fib_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u64 key; - u32 value; - show_mpls_fib_t *records = 0; - show_mpls_fib_t *s; - mpls_main_t * mm = &mpls_main; - ip4_fib_t * rx_fib; - - hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest, - ({ - vec_add2 (records, s, 1); - s->fib_index = (u32)(key>>32); - s->dest = (u32)(key & 0xFFFFFFFF); - s->entry_index = (u32) value; - })); - - if (!vec_len(records)) - { - vlib_cli_output (vm, "MPLS encap table empty"); - } - /* sort output by dst address within fib */ - vec_sort_with_function (records, mpls_dest_cmp); - vec_sort_with_function (records, mpls_fib_index_cmp); - vlib_cli_output (vm, "MPLS encap table"); - vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels"); - vec_foreach (s, records) - { - rx_fib = ip4_fib_get (s->fib_index); - vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id, - format_ip4_address, &s->dest, - format_mpls_encap_index, mm, s->entry_index); - } - - vec_free(records); - return 0; -} - -VLIB_CLI_COMMAND (show_mpls_fib_command, static) = { - .path = "show mpls encap", - .short_help = "show mpls encap", - .function = show_mpls_fib_command_fn, -}; - -static clib_error_t * vnet_mpls_local_label (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { unformat_input_t _line_input, * line_input = &_line_input; fib_route_path_t *rpaths = NULL, rpath; - clib_error_t * error = 0; u32 table_id, is_del, is_ip; - fib_prefix_t pfx; mpls_label_t local_label; + mpls_label_t out_label; + clib_error_t * error; mpls_eos_bit_t eos; + vnet_main_t * vnm; + fib_prefix_t pfx; + vnm = vnet_get_main(); + error = NULL; is_ip = 0; table_id = 0; eos = MPLS_EOS; @@ -519,13 +246,99 @@ vnet_mpls_local_label (vlib_main_t * vm, pfx.fp_proto = FIB_PROTOCOL_IP6; is_ip = 1; } + else if (unformat (line_input, "via %U %U weight %u", + unformat_ip4_address, + &rpath.frp_addr.ip4, + unformat_vnet_sw_interface, vnm, + &rpath.frp_sw_if_index, + &rpath.frp_weight)) + { + rpath.frp_proto = FIB_PROTOCOL_IP4; + vec_add1(rpaths, rpath); + } + + else if (unformat (line_input, "via %U %U weight %u", + unformat_ip6_address, + &rpath.frp_addr.ip6, + unformat_vnet_sw_interface, vnm, + &rpath.frp_sw_if_index, + &rpath.frp_weight)) + { + rpath.frp_proto = FIB_PROTOCOL_IP6; + vec_add1(rpaths, rpath); + } + + else if (unformat (line_input, "via %U %U", + unformat_ip4_address, + &rpath.frp_addr.ip4, + unformat_vnet_sw_interface, vnm, + &rpath.frp_sw_if_index)) + { + rpath.frp_weight = 1; + rpath.frp_proto = FIB_PROTOCOL_IP4; + vec_add1(rpaths, rpath); + } + + else if (unformat (line_input, "via %U %U", + unformat_ip6_address, + &rpath.frp_addr.ip6, + unformat_vnet_sw_interface, vnm, + &rpath.frp_sw_if_index)) + { + rpath.frp_weight = 1; + rpath.frp_proto = FIB_PROTOCOL_IP6; + vec_add1(rpaths, rpath); + } + else if (unformat (line_input, "via %U next-hop-table %d", + unformat_ip4_address, + &rpath.frp_addr.ip4, + &rpath.frp_fib_index)) + { + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_proto = FIB_PROTOCOL_IP4; + vec_add1(rpaths, rpath); + } + else if (unformat (line_input, "via %U next-hop-table %d", + unformat_ip6_address, + &rpath.frp_addr.ip6, + &rpath.frp_fib_index)) + { + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_proto = FIB_PROTOCOL_IP6; + vec_add1(rpaths, rpath); + } + else if (unformat (line_input, "via %U", + unformat_ip4_address, + &rpath.frp_addr.ip4)) + { + /* + * the recursive next-hops are by default in the same table + * as the prefix + */ + rpath.frp_fib_index = table_id; + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_proto = FIB_PROTOCOL_IP4; + vec_add1(rpaths, rpath); + } + else if (unformat (line_input, "via %U", + unformat_ip6_address, + &rpath.frp_addr.ip6)) + { + rpath.frp_fib_index = table_id; + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_proto = FIB_PROTOCOL_IP6; + vec_add1(rpaths, rpath); + } else if (unformat (line_input, "%d", &local_label)) ; else if (unformat (line_input, "ip4-lookup-in-table %d", &rpath.frp_fib_index)) { - rpath.frp_label = MPLS_LABEL_INVALID; rpath.frp_proto = FIB_PROTOCOL_IP4; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; pfx.fp_payload_proto = DPO_PROTO_IP4; @@ -535,7 +348,6 @@ vnet_mpls_local_label (vlib_main_t * vm, "ip6-lookup-in-table %d", &rpath.frp_fib_index)) { - rpath.frp_label = MPLS_LABEL_INVALID; rpath.frp_proto = FIB_PROTOCOL_IP6; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; vec_add1(rpaths, rpath); @@ -545,16 +357,26 @@ vnet_mpls_local_label (vlib_main_t * vm, "mpls-lookup-in-table %d", &rpath.frp_fib_index)) { - rpath.frp_label = MPLS_LABEL_INVALID; rpath.frp_proto = FIB_PROTOCOL_MPLS; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; pfx.fp_payload_proto = DPO_PROTO_MPLS; vec_add1(rpaths, rpath); } + else if (unformat (line_input, "out-label %U", + unformat_mpls_unicast_label, + &out_label)) + { + if (vec_len(rpaths) == 0) + { + error = clib_error_return(0 , "Paths then labels"); + goto done; + } + vec_add1(rpaths[vec_len(rpaths)-1].frp_label_stack, out_label); + } else { error = clib_error_return (0, "unkown input: %U", - format_unformat_error, input); + format_unformat_error, line_input); goto done; } @@ -596,6 +418,7 @@ vnet_mpls_local_label (vlib_main_t * vm, pfx.fp_proto = FIB_PROTOCOL_MPLS; pfx.fp_len = 21; pfx.fp_label = local_label; + pfx.fp_payload_proto = DPO_PROTO_MPLS; if (NULL == rpaths) { @@ -606,17 +429,20 @@ vnet_mpls_local_label (vlib_main_t * vm, /* * the CLI parsing stored table Ids, swap to FIB indicies */ - fi = fib_table_id_find_fib_index(dpo_proto_to_fib(pfx.fp_payload_proto), - rpaths[0].frp_fib_index); - - if (~0 == fi) + if (FIB_NODE_INDEX_INVALID == rpath.frp_sw_if_index) { - error = clib_error_return(0 , "%U Via table %d does not exist", - format_fib_protocol, pfx.fp_payload_proto, - rpaths[0].frp_fib_index); - goto done; + fi = fib_table_id_find_fib_index(dpo_proto_to_fib(pfx.fp_payload_proto), + rpaths[0].frp_fib_index); + + if (~0 == fi) + { + error = clib_error_return(0 , "%U Via table %d does not exist", + format_fib_protocol, pfx.fp_payload_proto, + rpaths[0].frp_fib_index); + goto done; + } + rpaths[0].frp_fib_index = fi; } - rpaths[0].frp_fib_index = fi; fib_index = mpls_fib_index_from_table_id(table_id); @@ -653,44 +479,15 @@ VLIB_CLI_COMMAND (mpls_local_label_command, static) = { .short_help = "Create/Delete MPL local labels", }; -int mpls_fib_reset_labels (u32 fib_id) +int +mpls_fib_reset_labels (u32 fib_id) { - u64 key; - u32 value; - show_mpls_fib_t *records = 0; - show_mpls_fib_t *s; - mpls_main_t * mm = &mpls_main; - ip4_main_t * im = &ip4_main; - u32 fib_index; - uword *p; - - p = hash_get (im->fib_index_by_table_id, fib_id); - if (! p) - return VNET_API_ERROR_NO_SUCH_FIB; - - fib_index = p[0]; - - hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest, - ({ - if (fib_index == (u32)(key>>32)) { - vec_add2 (records, s, 1); - s->dest = (u32)(key & 0xFFFFFFFF); - s->entry_index = (u32) value; - } - })); - - vec_foreach (s, records) - { - key = ((u64)fib_index<<32) | ((u64) s->dest); - hash_unset (mm->mpls_encap_by_fib_and_dest, key); - pool_put_index (mm->encaps, s->entry_index); - } - - vec_free(records); + // FIXME return 0; } -static clib_error_t * mpls_init (vlib_main_t * vm) +static clib_error_t * +mpls_init (vlib_main_t * vm) { mpls_main_t * mm = &mpls_main; clib_error_t * error; @@ -701,8 +498,6 @@ static clib_error_t * mpls_init (vlib_main_t * vm) if ((error = vlib_call_init_function (vm, ip_main_init))) return error; - mm->mpls_encap_by_fib_and_dest = hash_create (0, sizeof (uword)); - return vlib_call_init_function (vm, mpls_input_init); } |