blob: 9f6579cda89929445e4ff7c12de6346189330435 [file] [log] [blame]
Steven9cd2d7a2017-12-20 12:43:01 -08001/*
2 *------------------------------------------------------------------
3 * Copyright (c) 2017 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
16 */
17
18#define _GNU_SOURCE
19#include <stdint.h>
20#include <vnet/llc/llc.h>
21#include <vnet/snap/snap.h>
22#include <vnet/bonding/node.h>
23
Benoît Ganne47727c02019-02-12 13:35:08 +010024#ifndef CLIB_MARCH_VARIANT
Steven9cd2d7a2017-12-20 12:43:01 -080025bond_main_t bond_main;
Benoît Ganne47727c02019-02-12 13:35:08 +010026#endif /* CLIB_MARCH_VARIANT */
Steven9cd2d7a2017-12-20 12:43:01 -080027
28#define foreach_bond_input_error \
29 _(NONE, "no error") \
30 _(IF_DOWN, "interface down") \
Damjan Marion5e5adb32018-05-26 00:50:39 +020031 _(PASS_THRU, "pass through (CDP, LLDP, slow protocols)")
Steven9cd2d7a2017-12-20 12:43:01 -080032
33typedef enum
34{
35#define _(f,s) BOND_INPUT_ERROR_##f,
36 foreach_bond_input_error
37#undef _
38 BOND_INPUT_N_ERROR,
39} bond_input_error_t;
40
41static char *bond_input_error_strings[] = {
42#define _(n,s) s,
43 foreach_bond_input_error
44#undef _
45};
46
47static u8 *
48format_bond_input_trace (u8 * s, va_list * args)
49{
50 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
51 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
52 bond_packet_trace_t *t = va_arg (*args, bond_packet_trace_t *);
Steven9cd2d7a2017-12-20 12:43:01 -080053
Steven70488ab2018-03-28 17:59:00 -070054 s = format (s, "src %U, dst %U, %U -> %U",
Steven9cd2d7a2017-12-20 12:43:01 -080055 format_ethernet_address, t->ethernet.src_address,
56 format_ethernet_address, t->ethernet.dst_address,
Steven70488ab2018-03-28 17:59:00 -070057 format_vnet_sw_if_index_name, vnet_get_main (),
58 t->sw_if_index,
59 format_vnet_sw_if_index_name, vnet_get_main (),
60 t->bond_sw_if_index);
Steven9cd2d7a2017-12-20 12:43:01 -080061
62 return s;
63}
Damjan Marion5e5adb32018-05-26 00:50:39 +020064
65typedef enum
66{
67 BOND_INPUT_NEXT_DROP,
68 BOND_INPUT_N_NEXT,
Steven9f781d82018-06-05 11:09:32 -070069} bond_output_next_t;
Steven9cd2d7a2017-12-20 12:43:01 -080070
71static_always_inline u8
72packet_is_cdp (ethernet_header_t * eth)
73{
74 llc_header_t *llc;
75 snap_header_t *snap;
76
77 llc = (llc_header_t *) (eth + 1);
78 snap = (snap_header_t *) (llc + 1);
79
80 return ((eth->type == htons (ETHERNET_TYPE_CDP)) ||
81 ((llc->src_sap == 0xAA) && (llc->control == 0x03) &&
82 (snap->protocol == htons (0x2000)) &&
83 (snap->oui[0] == 0) && (snap->oui[1] == 0) &&
84 (snap->oui[2] == 0x0C)));
85}
86
Steven Luongc94afaa2019-07-24 21:16:09 -070087static inline void
Damjan Marion5e5adb32018-05-26 00:50:39 +020088bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node,
Steven Luongc94afaa2019-07-24 21:16:09 -070089 vlib_buffer_t * b, u32 bond_sw_if_index,
90 u32 * n_rx_packets, u32 * n_rx_bytes)
Steven9cd2d7a2017-12-20 12:43:01 -080091{
Steven9cd2d7a2017-12-20 12:43:01 -080092 u16 *ethertype_p, ethertype;
93 ethernet_vlan_header_t *vlan;
Damjan Marion5e5adb32018-05-26 00:50:39 +020094 ethernet_header_t *eth = (ethernet_header_t *) vlib_buffer_get_current (b);
Steven9cd2d7a2017-12-20 12:43:01 -080095
Steven Luongc94afaa2019-07-24 21:16:09 -070096 (*n_rx_packets)++;
97 *n_rx_bytes += b->current_length;
Damjan Marion5e5adb32018-05-26 00:50:39 +020098 ethertype = clib_mem_unaligned (&eth->type, u16);
99 if (!ethernet_frame_is_tagged (ntohs (ethertype)))
Steven9cd2d7a2017-12-20 12:43:01 -0800100 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200101 // Let some layer2 packets pass through.
102 if (PREDICT_TRUE ((ethertype != htons (ETHERNET_TYPE_SLOW_PROTOCOLS))
103 && !packet_is_cdp (eth)
104 && (ethertype != htons (ETHERNET_TYPE_802_1_LLDP))))
Steven9cd2d7a2017-12-20 12:43:01 -0800105 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200106 /* Change the physical interface to bond interface */
107 vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
Steven Luongc94afaa2019-07-24 21:16:09 -0700108 return;
Steven9cd2d7a2017-12-20 12:43:01 -0800109 }
110 }
111 else
112 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200113 vlan = (void *) (eth + 1);
114 ethertype_p = &vlan->type;
115 ethertype = clib_mem_unaligned (ethertype_p, u16);
116 if (ethertype == ntohs (ETHERNET_TYPE_VLAN))
117 {
118 vlan++;
119 ethertype_p = &vlan->type;
120 }
121 ethertype = clib_mem_unaligned (ethertype_p, u16);
122 if (PREDICT_TRUE ((ethertype != htons (ETHERNET_TYPE_SLOW_PROTOCOLS))
123 && (ethertype != htons (ETHERNET_TYPE_CDP))
124 && (ethertype != htons (ETHERNET_TYPE_802_1_LLDP))))
125 {
126 /* Change the physical interface to bond interface */
127 vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
Steven Luongc94afaa2019-07-24 21:16:09 -0700128 return;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200129 }
Steven9cd2d7a2017-12-20 12:43:01 -0800130 }
131
Damjan Marion5e5adb32018-05-26 00:50:39 +0200132 vlib_error_count (vm, node->node_index, BOND_INPUT_ERROR_PASS_THRU, 1);
Steven Luongc94afaa2019-07-24 21:16:09 -0700133 return;
Steven9cd2d7a2017-12-20 12:43:01 -0800134}
135
Damjan Marion5e5adb32018-05-26 00:50:39 +0200136static inline void
137bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node,
138 u32 * last_slave_sw_if_index, u32 slave_sw_if_index,
Damjan Marion5e5adb32018-05-26 00:50:39 +0200139 u32 * bond_sw_if_index, vlib_buffer_t * b,
140 u32 * next_index, vlib_error_t * error)
Steven9cd2d7a2017-12-20 12:43:01 -0800141{
Damjan Marion5e5adb32018-05-26 00:50:39 +0200142 slave_if_t *sif;
143 bond_if_t *bif;
144
Steven Luong71e5b472019-10-10 11:36:41 -0700145 *next_index = BOND_INPUT_NEXT_DROP;
146 *error = 0;
147
Damjan Marion5e5adb32018-05-26 00:50:39 +0200148 if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index))
Steven Luong71e5b472019-10-10 11:36:41 -0700149 goto next;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200150
Damjan Marion5e5adb32018-05-26 00:50:39 +0200151 *last_slave_sw_if_index = slave_sw_if_index;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200152
153 sif = bond_get_slave_by_sw_if_index (slave_sw_if_index);
154 ASSERT (sif);
155
156 bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
157
158 ASSERT (bif);
159 ASSERT (vec_len (bif->slaves));
160
161 if (PREDICT_TRUE (bif->admin_up == 0))
162 {
163 *bond_sw_if_index = slave_sw_if_index;
164 *error = node->errors[BOND_INPUT_ERROR_IF_DOWN];
165 }
166
167 *bond_sw_if_index = bif->sw_if_index;
Steven Luong71e5b472019-10-10 11:36:41 -0700168
169next:
Damjan Marion7d98a122018-07-19 20:42:08 +0200170 vnet_feature_next (next_index, b);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200171}
172
Steven Luong71e5b472019-10-10 11:36:41 -0700173static_always_inline void
174bond_update_next_x4 (vlib_buffer_t * b0, vlib_buffer_t * b1,
175 vlib_buffer_t * b2, vlib_buffer_t * b3)
176{
177 u32 tmp0, tmp1, tmp2, tmp3;
178
179 tmp0 = tmp1 = tmp2 = tmp3 = BOND_INPUT_NEXT_DROP;
180 vnet_feature_next (&tmp0, b0);
181 vnet_feature_next (&tmp1, b1);
182 vnet_feature_next (&tmp2, b2);
183 vnet_feature_next (&tmp3, b3);
184}
185
Damjan Marion812b32d2018-05-28 21:26:47 +0200186VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
187 vlib_node_runtime_t * node,
188 vlib_frame_t * frame)
Damjan Marion5e5adb32018-05-26 00:50:39 +0200189{
Damjan Marion067cd622018-07-11 12:47:43 +0200190 u16 thread_index = vm->thread_index;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200191 u32 *from, n_left;
192 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
193 u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index;
194 u16 nexts[VLIB_FRAME_SIZE], *next;
195 u32 last_slave_sw_if_index = ~0;
196 u32 bond_sw_if_index = 0;
197 vlib_error_t error = 0;
198 u32 next_index = 0;
Steven Luongc94afaa2019-07-24 21:16:09 -0700199 u32 n_rx_bytes = 0, n_rx_packets = 0;
Steven9cd2d7a2017-12-20 12:43:01 -0800200
201 /* Vector of buffer / pkt indices we're supposed to process */
202 from = vlib_frame_vector_args (frame);
203
204 /* Number of buffers / pkts */
Damjan Marion5e5adb32018-05-26 00:50:39 +0200205 n_left = frame->n_vectors;
Steven9cd2d7a2017-12-20 12:43:01 -0800206
Damjan Marion5e5adb32018-05-26 00:50:39 +0200207 vlib_get_buffers (vm, from, bufs, n_left);
Steven9cd2d7a2017-12-20 12:43:01 -0800208
Damjan Marion5e5adb32018-05-26 00:50:39 +0200209 b = bufs;
210 next = nexts;
211 sw_if_index = sw_if_indices;
212
213 while (n_left >= 4)
Steven9cd2d7a2017-12-20 12:43:01 -0800214 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200215 u32 x = 0;
216 /* Prefetch next iteration */
217 if (PREDICT_TRUE (n_left >= 16))
Steven9cd2d7a2017-12-20 12:43:01 -0800218 {
Damjan Mariond30bf012018-11-18 23:48:43 +0100219 vlib_prefetch_buffer_data (b[8], LOAD);
220 vlib_prefetch_buffer_data (b[9], LOAD);
221 vlib_prefetch_buffer_data (b[10], LOAD);
222 vlib_prefetch_buffer_data (b[11], LOAD);
Steven9cd2d7a2017-12-20 12:43:01 -0800223
Damjan Marion5e5adb32018-05-26 00:50:39 +0200224 vlib_prefetch_buffer_header (b[12], LOAD);
225 vlib_prefetch_buffer_header (b[13], LOAD);
226 vlib_prefetch_buffer_header (b[14], LOAD);
227 vlib_prefetch_buffer_header (b[15], LOAD);
Steven9cd2d7a2017-12-20 12:43:01 -0800228 }
229
Damjan Marion5e5adb32018-05-26 00:50:39 +0200230 sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
231 sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
232 sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
233 sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
234
235 x |= sw_if_index[0] ^ last_slave_sw_if_index;
236 x |= sw_if_index[1] ^ last_slave_sw_if_index;
237 x |= sw_if_index[2] ^ last_slave_sw_if_index;
238 x |= sw_if_index[3] ^ last_slave_sw_if_index;
239
240 if (PREDICT_TRUE (x == 0))
Steven9cd2d7a2017-12-20 12:43:01 -0800241 {
Steven Luong71e5b472019-10-10 11:36:41 -0700242 /*
243 * Optimize to call update_next only if there is a feature arc
244 * after bond-input. Test feature count greater than 1 because
245 * bond-input itself is a feature arc for this slave interface.
246 */
247 ASSERT ((vnet_buffer (b[0])->feature_arc_index ==
248 vnet_buffer (b[1])->feature_arc_index) &&
249 (vnet_buffer (b[0])->feature_arc_index ==
250 vnet_buffer (b[2])->feature_arc_index) &&
251 (vnet_buffer (b[0])->feature_arc_index ==
252 vnet_buffer (b[3])->feature_arc_index));
253 if (PREDICT_FALSE (vnet_get_feature_count
254 (vnet_buffer (b[0])->feature_arc_index,
255 last_slave_sw_if_index) > 1))
256 bond_update_next_x4 (b[0], b[1], b[2], b[3]);
257
Damjan Marion5e5adb32018-05-26 00:50:39 +0200258 next[0] = next[1] = next[2] = next[3] = next_index;
259 if (next_index == BOND_INPUT_NEXT_DROP)
Steven9cd2d7a2017-12-20 12:43:01 -0800260 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200261 b[0]->error = error;
262 b[1]->error = error;
263 b[2]->error = error;
264 b[3]->error = error;
Steven9cd2d7a2017-12-20 12:43:01 -0800265 }
Damjan Marion5e5adb32018-05-26 00:50:39 +0200266 else
Steven70488ab2018-03-28 17:59:00 -0700267 {
Steven Luongc94afaa2019-07-24 21:16:09 -0700268 bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
269 &n_rx_packets, &n_rx_bytes);
270 bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index,
271 &n_rx_packets, &n_rx_bytes);
272 bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index,
273 &n_rx_packets, &n_rx_bytes);
274 bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index,
275 &n_rx_packets, &n_rx_bytes);
Steven70488ab2018-03-28 17:59:00 -0700276 }
Steven9cd2d7a2017-12-20 12:43:01 -0800277 }
Damjan Marion5e5adb32018-05-26 00:50:39 +0200278 else
279 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200280 bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
Steven Luongc94afaa2019-07-24 21:16:09 -0700281 &bond_sw_if_index, b[0], &next_index, &error);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200282 next[0] = next_index;
283 if (next_index == BOND_INPUT_NEXT_DROP)
284 b[0]->error = error;
285 else
Steven Luongc94afaa2019-07-24 21:16:09 -0700286 bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
287 &n_rx_packets, &n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200288
289 bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[1],
Steven Luongc94afaa2019-07-24 21:16:09 -0700290 &bond_sw_if_index, b[1], &next_index, &error);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200291 next[1] = next_index;
292 if (next_index == BOND_INPUT_NEXT_DROP)
293 b[1]->error = error;
294 else
Steven Luongc94afaa2019-07-24 21:16:09 -0700295 bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index,
296 &n_rx_packets, &n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200297
298 bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[2],
Steven Luongc94afaa2019-07-24 21:16:09 -0700299 &bond_sw_if_index, b[2], &next_index, &error);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200300 next[2] = next_index;
301 if (next_index == BOND_INPUT_NEXT_DROP)
302 b[2]->error = error;
303 else
Steven Luongc94afaa2019-07-24 21:16:09 -0700304 bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index,
305 &n_rx_packets, &n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200306
307 bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[3],
Steven Luongc94afaa2019-07-24 21:16:09 -0700308 &bond_sw_if_index, b[3], &next_index, &error);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200309 next[3] = next_index;
310 if (next_index == BOND_INPUT_NEXT_DROP)
311 b[3]->error = error;
312 else
Steven Luongc94afaa2019-07-24 21:16:09 -0700313 bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index,
314 &n_rx_packets, &n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200315 }
316
317 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
318 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[1]);
319 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[2]);
320 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[3]);
321
322 /* next */
323 n_left -= 4;
324 b += 4;
325 sw_if_index += 4;
326 next += 4;
Steven9cd2d7a2017-12-20 12:43:01 -0800327 }
328
Damjan Marion5e5adb32018-05-26 00:50:39 +0200329 while (n_left)
330 {
331 sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
332 bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
Steven Luongc94afaa2019-07-24 21:16:09 -0700333 &bond_sw_if_index, b[0], &next_index, &error);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200334 next[0] = next_index;
335 if (next_index == BOND_INPUT_NEXT_DROP)
336 b[0]->error = error;
337 else
Steven Luongc94afaa2019-07-24 21:16:09 -0700338 bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
339 &n_rx_packets, &n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200340
341 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
342
343 /* next */
344 n_left -= 1;
345 b += 1;
346 sw_if_index += 1;
347 next += 1;
348 }
349
350 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
351 {
352 n_left = frame->n_vectors; /* number of packets to process */
353 b = bufs;
354 sw_if_index = sw_if_indices;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200355 bond_packet_trace_t *t0;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200356
Damjan Marionf264f082018-05-30 00:03:34 +0200357 while (n_left)
Damjan Marion5e5adb32018-05-26 00:50:39 +0200358 {
359 if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
360 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200361 t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
362 t0->sw_if_index = sw_if_index[0];
Dave Barach178cf492018-11-13 16:34:13 -0500363 clib_memcpy_fast (&t0->ethernet, vlib_buffer_get_current (b[0]),
364 sizeof (ethernet_header_t));
Damjan Marion5e5adb32018-05-26 00:50:39 +0200365 t0->bond_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
366 }
367 /* next */
368 n_left--;
369 b++;
370 sw_if_index++;
Damjan Marion5e5adb32018-05-26 00:50:39 +0200371 }
372 }
373
374 /* increase rx counters */
Steven Luongc94afaa2019-07-24 21:16:09 -0700375 vlib_increment_combined_counter
376 (vnet_main.interface_main.combined_sw_if_counters +
377 VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, n_rx_packets,
378 n_rx_bytes);
Damjan Marion5e5adb32018-05-26 00:50:39 +0200379
380 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
Steven9cd2d7a2017-12-20 12:43:01 -0800381 vlib_node_increment_counter (vm, bond_input_node.index,
382 BOND_INPUT_ERROR_NONE, frame->n_vectors);
383
Steven9cd2d7a2017-12-20 12:43:01 -0800384 return frame->n_vectors;
385}
386
387static clib_error_t *
388bond_input_init (vlib_main_t * vm)
389{
390 return 0;
391}
392
393/* *INDENT-OFF* */
394VLIB_REGISTER_NODE (bond_input_node) = {
Steven9cd2d7a2017-12-20 12:43:01 -0800395 .name = "bond-input",
396 .vector_size = sizeof (u32),
397 .format_buffer = format_ethernet_header_with_length,
398 .format_trace = format_bond_input_trace,
399 .type = VLIB_NODE_TYPE_INTERNAL,
400 .n_errors = BOND_INPUT_N_ERROR,
401 .error_strings = bond_input_error_strings,
Damjan Marion5e5adb32018-05-26 00:50:39 +0200402 .n_next_nodes = BOND_INPUT_N_NEXT,
Steven9cd2d7a2017-12-20 12:43:01 -0800403 .next_nodes =
404 {
Damjan Marion5e5adb32018-05-26 00:50:39 +0200405 [BOND_INPUT_NEXT_DROP] = "error-drop"
Steven9cd2d7a2017-12-20 12:43:01 -0800406 }
407};
408
409VLIB_INIT_FUNCTION (bond_input_init);
410
411VNET_FEATURE_INIT (bond_input, static) =
412{
413 .arc_name = "device-input",
414 .node_name = "bond-input",
415 .runs_before = VNET_FEATURES ("ethernet-input"),
416};
Steven9cd2d7a2017-12-20 12:43:01 -0800417/* *INDENT-ON* */
418
419static clib_error_t *
420bond_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
421{
422 bond_main_t *bm = &bond_main;
423 slave_if_t *sif;
424 vlib_main_t *vm = bm->vlib_main;
425
426 sif = bond_get_slave_by_sw_if_index (sw_if_index);
427 if (sif)
428 {
Stevene43278f2019-01-17 15:11:29 -0800429 if (sif->lacp_enabled)
430 return 0;
431
Steven Luongbac326c2019-08-05 09:47:58 -0700432 /* port_enabled is both admin up and hw link up */
433 sif->port_enabled = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) &&
434 vnet_sw_interface_is_link_up (vnm, sw_if_index));
Steven9cd2d7a2017-12-20 12:43:01 -0800435 if (sif->port_enabled == 0)
Steven Luongbac326c2019-08-05 09:47:58 -0700436 bond_disable_collecting_distributing (vm, sif);
Steven9cd2d7a2017-12-20 12:43:01 -0800437 else
Steven Luongbac326c2019-08-05 09:47:58 -0700438 bond_enable_collecting_distributing (vm, sif);
Steven9cd2d7a2017-12-20 12:43:01 -0800439 }
440
441 return 0;
442}
443
444VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bond_sw_interface_up_down);
445
446static clib_error_t *
447bond_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
448{
449 bond_main_t *bm = &bond_main;
450 slave_if_t *sif;
451 vnet_sw_interface_t *sw;
452 vlib_main_t *vm = bm->vlib_main;
Steven9cd2d7a2017-12-20 12:43:01 -0800453
Stevence2db6a2018-04-23 17:06:24 -0700454 sw = vnet_get_hw_sw_interface (vnm, hw_if_index);
Steven9cd2d7a2017-12-20 12:43:01 -0800455 sif = bond_get_slave_by_sw_if_index (sw->sw_if_index);
456 if (sif)
457 {
Stevene43278f2019-01-17 15:11:29 -0800458 if (sif->lacp_enabled)
459 return 0;
460
Steven Luongbac326c2019-08-05 09:47:58 -0700461 /* port_enabled is both admin up and hw link up */
462 sif->port_enabled = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) &&
463 vnet_sw_interface_is_admin_up (vnm,
464 sw->sw_if_index));
465 if (sif->port_enabled == 0)
466 bond_disable_collecting_distributing (vm, sif);
467 else
468 bond_enable_collecting_distributing (vm, sif);
Steven9cd2d7a2017-12-20 12:43:01 -0800469 }
470
471 return 0;
472}
473
474VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bond_hw_interface_up_down);
Steven9cd2d7a2017-12-20 12:43:01 -0800475
476/*
477 * fd.io coding-style-patch-verification: ON
478 *
479 * Local Variables:
480 * eval: (c-set-style "gnu")
481 * End:
482 */