docs: vnet comment nitfixes
[vpp.git] / src / vnet / mpls / interface.c
1 /*
2  * interface.c: mpls interfaces
3  *
4  * Copyright (c) 2012 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/vnet.h>
19 #include <vnet/mpls/mpls.h>
20 #include <vnet/fib/mpls_fib.h>
21 #include <vnet/fib/ip4_fib.h>
22 #include <vnet/adj/adj_midchain.h>
23 #include <vnet/dpo/classify_dpo.h>
24
25
26 u8
27 mpls_sw_interface_is_enabled (u32 sw_if_index)
28 {
29     mpls_main_t * mm = &mpls_main;
30
31     if (vec_len(mm->mpls_enabled_by_sw_if_index) <= sw_if_index)
32         return (0);
33
34     return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
35 }
36
37 int
38 mpls_sw_interface_enable_disable (mpls_main_t * mm,
39                                   u32 sw_if_index,
40                                   u8 is_enable,
41                                   u8 is_api)
42 {
43   fib_node_index_t lfib_index;
44   vnet_main_t *vnm = vnet_get_main ();
45   vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
46
47   vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
48
49   lfib_index = fib_table_find(FIB_PROTOCOL_MPLS,
50                               MPLS_FIB_DEFAULT_TABLE_ID);
51
52   if (~0 == lfib_index)
53        return VNET_API_ERROR_NO_SUCH_FIB;
54
55   /*
56    * enable/disable only on the 1<->0 transition
57    */
58   if (is_enable)
59     {
60       if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
61           return (0);
62
63       fib_table_lock(lfib_index, FIB_PROTOCOL_MPLS,
64                      (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
65
66       vec_validate(mm->fib_index_by_sw_if_index, sw_if_index);
67       mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
68     }
69   else
70     {
71       ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
72       if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
73           return (0);
74
75       fib_table_unlock(mm->fib_index_by_sw_if_index[sw_if_index],
76                        FIB_PROTOCOL_MPLS,
77                        (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
78     }
79
80   vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled",
81                                sw_if_index, !is_enable, 0, 0);
82
83   if (is_enable)
84     hi->l3_if_count++;
85   else if (hi->l3_if_count)
86     hi->l3_if_count--;
87
88   return (0);
89 }
90
91 static clib_error_t *
92 mpls_interface_enable_disable (vlib_main_t * vm,
93                                unformat_input_t * input,
94                                vlib_cli_command_t * cmd)
95 {
96   vnet_main_t * vnm = vnet_get_main();
97   clib_error_t * error = 0;
98   u32 sw_if_index, enable;
99   int rv;
100
101   sw_if_index = ~0;
102
103   if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
104     {
105       error = clib_error_return (0, "unknown interface `%U'",
106                                  format_unformat_error, input);
107       goto done;
108     }
109
110   if (unformat (input, "enable"))
111       enable = 1;
112   else if (unformat (input, "disable"))
113       enable = 0;
114   else
115     {
116       error = clib_error_return (0, "expected 'enable' or 'disable'",
117                                  format_unformat_error, input);
118       goto done;
119     }
120
121   rv = mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable, 0);
122
123   if (VNET_API_ERROR_NO_SUCH_FIB == rv)
124       error = clib_error_return (0, "default MPLS table must be created first");
125
126  done:
127   return error;
128 }
129
130 /*?
131  * This command enables an interface to accept MPLS packets
132  *
133  * @cliexpar
134  * @cliexstart{set interface mpls}
135  *  set interface mpls GigEthernet0/8/0 enable
136  * @cliexend
137  ?*/
138 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = {
139   .path = "set interface mpls",
140   .function = mpls_interface_enable_disable,
141   .short_help = "Enable/Disable an interface for MPLS forwarding",
142 };
143
144 static void
145 show_mpls_one_interface (vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index,
146                          bool verbose)
147 {
148   mpls_main_t *mm = &mpls_main;
149   u8 enabled;
150
151   enabled = mm->mpls_enabled_by_sw_if_index[sw_if_index];
152
153   if (enabled)
154     {
155       vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnm,
156                        sw_if_index);
157       vlib_cli_output (vm, "  MPLS enabled");
158     }
159   else if (verbose)
160     {
161       vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnm,
162                        sw_if_index);
163       vlib_cli_output (vm, "  MPLS disabled");
164     }
165 }
166
167 static walk_rc_t
168 show_mpls_interface_walk (vnet_main_t *vnm, vnet_sw_interface_t *si, void *ctx)
169 {
170   show_mpls_one_interface (vnm, ctx, si->sw_if_index, false);
171
172   return (WALK_CONTINUE);
173 }
174
175 static clib_error_t *
176 show_mpls_interface (vlib_main_t *vm, unformat_input_t *input,
177                      vlib_cli_command_t *cmd)
178 {
179   vnet_main_t *vnm = vnet_get_main ();
180   u32 sw_if_index;
181
182   sw_if_index = ~0;
183
184   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
185     ;
186
187   if (~0 == sw_if_index)
188     {
189       vnet_sw_interface_walk (vnm, show_mpls_interface_walk, vm);
190     }
191   else
192     {
193       show_mpls_one_interface (vnm, vm, sw_if_index, true);
194     }
195
196   return NULL;
197 }
198
199 /*?
200  * This command displays the MPLS forwarding state of an interface
201  *
202  * @cliexpar
203  * @cliexstart{show mpls interface}
204  *  set mpls interface GigEthernet0/8/0
205  * @cliexend
206  ?*/
207 VLIB_CLI_COMMAND (show_mpls_interface_command, static) = {
208   .path = "show mpls interface",
209   .function = show_mpls_interface,
210   .short_help = "Show MPLS interface forwarding",
211 };