Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : #include <vnet/ip/ip.h>
16 : #include <vnet/ethernet/ethernet.h>
17 : #include <vnet/adj/adj.h>
18 : #include <vnet/fib/fib_table.h>
19 :
20 : typedef struct
21 : {
22 : u8 mac_addr[6];
23 : } mac_addr_t;
24 :
25 : static clib_error_t *
26 0 : virtual_ip_cmd_fn_command_fn (vlib_main_t * vm,
27 : unformat_input_t * input,
28 : vlib_cli_command_t * cmd)
29 : {
30 0 : unformat_input_t _line_input, *line_input = &_line_input;
31 0 : vnet_main_t *vnm = vnet_get_main ();
32 : ip46_address_t next_hop, *next_hops;
33 : fib_route_path_t *rpaths;
34 : fib_prefix_t prefix;
35 : u8 mac_addr[6];
36 0 : mac_addr_t *mac_addrs = 0;
37 : u32 sw_if_index;
38 : u32 i;
39 0 : clib_error_t *error = NULL;
40 :
41 0 : next_hops = NULL;
42 0 : rpaths = NULL;
43 0 : prefix.fp_len = 32;
44 0 : prefix.fp_proto = FIB_PROTOCOL_IP4;
45 :
46 : /* Get a line of input. */
47 0 : if (!unformat_user (input, unformat_line_input, line_input))
48 0 : return 0;
49 :
50 0 : if (!unformat (line_input, "%U %U",
51 : unformat_ip4_address, &prefix.fp_addr.ip4,
52 : unformat_vnet_sw_interface, vnm, &sw_if_index))
53 : {
54 0 : error = clib_error_return (0, "unknown input `%U'",
55 : format_unformat_error, line_input);
56 0 : goto done;
57 : }
58 :
59 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
60 : {
61 0 : if (unformat (line_input, "mac %U",
62 : unformat_ethernet_address, &mac_addr))
63 : {
64 : mac_addr_t *ma;
65 0 : vec_add2 (mac_addrs, ma, 1);
66 0 : clib_memcpy (ma, mac_addr, sizeof (mac_addr));
67 : }
68 0 : else if (unformat (line_input, "next-hop %U",
69 : unformat_ip4_address, &next_hop.ip4))
70 : {
71 0 : vec_add1 (next_hops, next_hop);
72 : }
73 : else
74 : {
75 0 : error = clib_error_return (0, "unknown input `%U'",
76 : format_unformat_error, line_input);
77 0 : goto done;
78 : }
79 : }
80 :
81 0 : if (vec_len (mac_addrs) == 0 || vec_len (mac_addrs) != vec_len (next_hops))
82 : {
83 0 : error = clib_error_return (0, "unknown input `%U'",
84 : format_unformat_error, line_input);
85 0 : goto done;
86 : }
87 :
88 : /* Create / delete special interface route /32's */
89 :
90 0 : for (i = 0; i < vec_len (mac_addrs); i++)
91 : {
92 : fib_route_path_t *rpath;
93 :
94 0 : adj_nbr_add_or_lock_w_rewrite (FIB_PROTOCOL_IP4,
95 : VNET_LINK_IP4,
96 0 : &next_hops[i],
97 0 : sw_if_index, mac_addrs[i].mac_addr);
98 :
99 0 : vec_add2 (rpaths, rpath, 1);
100 :
101 0 : rpath->frp_proto = DPO_PROTO_IP4;
102 0 : rpath->frp_addr = next_hops[i];
103 0 : rpath->frp_sw_if_index = sw_if_index;
104 0 : rpath->frp_fib_index = ~0;
105 0 : rpath->frp_weight = 1;
106 0 : rpath->frp_label_stack = NULL;
107 : }
108 :
109 0 : fib_table_entry_path_add2 (0, // default FIB table
110 : &prefix,
111 : FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, rpaths);
112 :
113 0 : done:
114 0 : vec_free (mac_addrs);
115 0 : vec_free (next_hops);
116 0 : vec_free (rpaths);
117 0 : unformat_free (line_input);
118 :
119 0 : return error;
120 : }
121 :
122 : /* *INDENT-OFF* */
123 285289 : VLIB_CLI_COMMAND (virtual_ip_cmd_fn_command, static) = {
124 : .path = "ip virtual",
125 : .short_help = "ip virtual <addr> <interface> [mac <Mi>]+ [next-hop <ip4_address>]+",
126 : .function = virtual_ip_cmd_fn_command_fn,
127 : };
128 : /* *INDENT-ON* */
129 :
130 : /*
131 : * fd.io coding-style-patch-verification: ON
132 : *
133 : * Local Variables:
134 : * eval: (c-set-style "gnu")
135 : * End:
136 : */
|