gbp: disable L2 BD learning per-interface
[vpp.git] / src / plugins / gbp / gbp_itf.c
1 /*
2  * Copyright (c) 2018 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
16 #include <plugins/gbp/gbp_itf.h>
17 #include <plugins/gbp/gbp_bridge_domain.h>
18
19 /**
20  * Attributes and configurations attached to interfaces by GBP
21  */
22 typedef struct gbp_itf_t_
23 {
24   /**
25    * Number of references to this interface
26    */
27   u32 gi_locks;
28
29   u32 gi_sw_if_index;
30   u32 gi_bd_index;
31
32   /**
33    * L2/L3 Features configured by each user
34    */
35   u32 *gi_l2_input_fbs;
36   u32 gi_l2_input_fb;
37   u32 *gi_l2_output_fbs;
38   u32 gi_l2_output_fb;
39 } gbp_itf_t;
40
41 static gbp_itf_t *gbp_itfs;
42
43 static gbp_itf_t *
44 gbp_itf_get (index_t gii)
45 {
46   vec_validate (gbp_itfs, gii);
47
48   return (&gbp_itfs[gii]);
49 }
50
51 static index_t
52 gbp_itf_get_itf (u32 sw_if_index)
53 {
54   return (sw_if_index);
55 }
56
57 index_t
58 gbp_itf_add_and_lock (u32 sw_if_index, u32 bd_index)
59 {
60   gbp_itf_t *gi;
61
62   gi = gbp_itf_get (gbp_itf_get_itf (sw_if_index));
63
64   if (0 == gi->gi_locks)
65     {
66       gi->gi_sw_if_index = sw_if_index;
67       gi->gi_bd_index = bd_index;
68
69       if (~0 != gi->gi_bd_index)
70         gbp_bridge_domain_itf_add (sw_if_index, bd_index,
71                                    L2_BD_PORT_TYPE_NORMAL);
72     }
73
74   gi->gi_locks++;
75
76   return (sw_if_index);
77 }
78
79 void
80 gbp_itf_unlock (index_t gii)
81 {
82   gbp_itf_t *gi;
83
84   gi = gbp_itf_get (gii);
85   ASSERT (gi->gi_locks > 0);
86   gi->gi_locks--;
87
88   if (0 == gi->gi_locks)
89     {
90       if (~0 != gi->gi_bd_index)
91         gbp_bridge_domain_itf_del (gi->gi_sw_if_index, gi->gi_bd_index,
92                                    L2_BD_PORT_TYPE_NORMAL);
93       vec_free (gi->gi_l2_input_fbs);
94       vec_free (gi->gi_l2_output_fbs);
95
96       memset (gi, 0, sizeof (*gi));
97     }
98 }
99
100 void
101 gbp_itf_set_l2_input_feature (index_t gii,
102                               index_t useri, l2input_feat_masks_t feats)
103 {
104   u32 diff_fb, new_fb, *fb, feat;
105   gbp_itf_t *gi;
106
107   gi = gbp_itf_get (gii);
108
109   if (gi->gi_bd_index == ~0)
110     return;
111
112   vec_validate (gi->gi_l2_input_fbs, useri);
113   gi->gi_l2_input_fbs[useri] = feats;
114
115   new_fb = 0;
116   vec_foreach (fb, gi->gi_l2_input_fbs)
117   {
118     new_fb |= *fb;
119   }
120
121   /* add new features */
122   diff_fb = (gi->gi_l2_input_fb ^ new_fb) & new_fb;
123
124   /* *INDENT-OFF* */
125   foreach_set_bit (feat, diff_fb,
126   ({
127     l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1);
128   }));
129   /* *INDENT-ON* */
130
131   /* remove unneeded features */
132   diff_fb = (gi->gi_l2_input_fb ^ new_fb) & gi->gi_l2_input_fb;
133
134   /* *INDENT-OFF* */
135   foreach_set_bit (feat, diff_fb,
136   ({
137     l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0);
138   }));
139   /* *INDENT-ON* */
140
141   gi->gi_l2_input_fb = new_fb;
142 }
143
144 void
145 gbp_itf_set_l2_output_feature (index_t gii,
146                                index_t useri, l2output_feat_masks_t feats)
147 {
148   u32 diff_fb, new_fb, *fb, feat;
149   gbp_itf_t *gi;
150
151   gi = gbp_itf_get (gii);
152
153   if (gi->gi_bd_index == ~0)
154     return;
155
156   vec_validate (gi->gi_l2_output_fbs, useri);
157   gi->gi_l2_output_fbs[useri] = feats;
158
159   new_fb = 0;
160   vec_foreach (fb, gi->gi_l2_output_fbs)
161   {
162     new_fb |= *fb;
163   }
164
165   /* add new features */
166   diff_fb = (gi->gi_l2_output_fb ^ new_fb) & new_fb;
167
168   /* *INDENT-OFF* */
169   foreach_set_bit (feat, diff_fb,
170   ({
171     l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1);
172   }));
173   /* *INDENT-ON* */
174
175   /* remove unneeded features */
176   diff_fb = (gi->gi_l2_output_fb ^ new_fb) & gi->gi_l2_output_fb;
177
178   /* *INDENT-OFF* */
179   foreach_set_bit (feat, diff_fb,
180   ({
181     l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0);
182   }));
183   /* *INDENT-ON* */
184
185   gi->gi_l2_output_fb = new_fb;
186 }
187
188 u8 *
189 format_gbp_itf (u8 * s, va_list * args)
190 {
191   index_t gii = va_arg (*args, index_t);
192   gbp_itf_t *gi;
193
194   gi = gbp_itf_get (gii);
195
196   s = format (s, "%U locks:%d bd-index:%d input-feats:%U output-feats:%U",
197               format_vnet_sw_if_index_name, vnet_get_main (),
198               gi->gi_sw_if_index, gi->gi_locks,
199               gi->gi_bd_index,
200               format_l2_input_features, gi->gi_l2_input_fb, 0,
201               format_l2_output_features, gi->gi_l2_output_fb, 0);
202
203   return (s);
204 }
205
206 static clib_error_t *
207 gbp_itf_show (vlib_main_t * vm,
208               unformat_input_t * input, vlib_cli_command_t * cmd)
209 {
210   u32 gii;
211
212   vlib_cli_output (vm, "Interfaces:");
213
214   vec_foreach_index (gii, gbp_itfs)
215   {
216     vlib_cli_output (vm, "  [%d] %U", gii, format_gbp_itf, gii);
217   }
218
219   return (NULL);
220 }
221
222 /*?
223  * Show Group Based Interfaces
224  *
225  * @cliexpar
226  * @cliexstart{show gbp contract}
227  * @cliexend
228  ?*/
229 /* *INDENT-OFF* */
230 VLIB_CLI_COMMAND (gbp_contract_show_node, static) = {
231   .path = "show gbp interface",
232   .short_help = "show gbp interface\n",
233   .function = gbp_itf_show,
234 };
235 /* *INDENT-ON* */
236
237
238 /*
239  * fd.io coding-style-patch-verification: ON
240  *
241  * Local Variables:
242  * eval: (c-set-style "gnu")
243  * End:
244  */