FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
input.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #define _GNU_SOURCE
17 #include <vnet/bonding/node.h>
18 #include <lacp/node.h>
19 
20 static int
22 {
23  lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt;
24 
25  if (lacpdu->subtype != LACP_SUBTYPE)
26  return LACP_ERROR_UNSUPPORTED;
27 
28  /*
29  * According to the spec, no checking on the version number and tlv types.
30  * But we may check the tlv lengths.
31  */
32  if ((lacpdu->actor.tlv_length != sizeof (lacp_actor_partner_t)) ||
33  (lacpdu->partner.tlv_length != sizeof (lacp_actor_partner_t)) ||
34  (lacpdu->collector.tlv_length != sizeof (lacp_collector_t)) ||
35  (lacpdu->terminator.tlv_length != 0))
36  return (LACP_ERROR_BAD_TLV);
37 
39  LACP_RX_EVENT_PDU_RECEIVED, &sif->rx_state);
40 
41  return LACP_ERROR_NONE;
42 }
43 
44 static void
45 marker_fill_pdu (marker_pdu_t * marker, slave_if_t * sif)
46 {
47  marker_pdu_t *pkt = (marker_pdu_t *) sif->last_marker_pkt;
48 
49  marker->marker_info = pkt->marker_info;
50  marker->marker_info.tlv_type = MARKER_RESPONSE_INFORMATION;
51 }
52 
53 void
54 marker_fill_request_pdu (marker_pdu_t * marker, slave_if_t * sif)
55 {
56  marker->marker_info.tlv_type = MARKER_INFORMATION;
57  marker->marker_info.requester_port = sif->actor.port_number;
58  clib_memcpy (marker->marker_info.requester_system, sif->actor.system, 6);
59  marker->marker_info.requester_transaction_id = sif->marker_tx_id;
60  sif->marker_tx_id++;
61 }
62 
63 static void
65 {
66  lacp_main_t *lm = &lacp_main;
67  u32 *to_next;
68  ethernet_marker_pdu_t *h0;
70  u32 bi0;
71  vlib_buffer_t *b0;
72  vlib_frame_t *f;
73  vlib_main_t *vm = lm->vlib_main;
74  vnet_main_t *vnm = lm->vnet_main;
75 
76  /*
77  * see lacp_periodic_init() to understand what's already painted
78  * into the buffer by the packet template mechanism
79  */
81  (vm, &lm->marker_packet_templates[sif->packet_template_index], &bi0);
82 
83  if (!h0)
84  return;
85 
86  /* Add the interface's ethernet source address */
87  hw = vnet_get_sup_hw_interface (vnm, sif->sw_if_index);
88 
89  clib_memcpy (h0->ethernet.src_address, hw->hw_address,
90  vec_len (hw->hw_address));
91 
92  marker_fill_pdu (&h0->marker, sif);
93 
94  /* Set the outbound packet length */
95  b0 = vlib_get_buffer (vm, bi0);
96  b0->current_length = sizeof (ethernet_marker_pdu_t);
97  b0->current_data = 0;
99 
100  /* And the outbound interface */
101  vnet_buffer (b0)->sw_if_index[VLIB_TX] = hw->sw_if_index;
102 
103  /* And output the packet on the correct interface */
105 
106  to_next = vlib_frame_vector_args (f);
107  to_next[0] = bi0;
108  f->n_vectors = 1;
109 
111 }
112 
113 static int
115 {
116  marker_pdu_t *marker = (marker_pdu_t *) sif->last_marker_pkt;
117 
118  /*
119  * According to the spec, no checking on the version number and tlv types.
120  * But we may check the tlv lengths.
121  */
122  if ((marker->marker_info.tlv_length != sizeof (marker_information_t)) ||
123  (marker->terminator.tlv_length != 0))
124  return (LACP_ERROR_BAD_TLV);
125 
127 
128  return LACP_ERROR_NONE;
129 }
130 
131 /*
132  * lacp input routine
133  */
136 {
137  lacp_main_t *lm = &lacp_main;
138  slave_if_t *sif;
139  uword nbytes;
140  lacp_error_t e;
141  marker_pdu_t *marker;
142  uword last_packet_signature;
143  bond_if_t *bif;
144 
145  sif =
147  if ((sif == 0) || (sif->mode != BOND_MODE_LACP))
148  {
149  return LACP_ERROR_DISABLED;
150  }
151 
152  /* Handle marker protocol */
153  marker = (marker_pdu_t *) (b0->data + b0->current_data);
154  if (marker->subtype == MARKER_SUBTYPE)
155  {
156  if (sif->last_marker_pkt)
157  _vec_len (sif->last_marker_pkt) = 0;
159  vlib_buffer_length_in_chain (vm, b0) - 1);
160  nbytes = vlib_buffer_contents (vm, bi0, sif->last_marker_pkt);
161  ASSERT (nbytes <= vec_len (sif->last_marker_pkt));
162  if (nbytes < sizeof (lacp_pdu_t))
163  return LACP_ERROR_TOO_SMALL;
164  return (handle_marker_protocol (vm, sif));
165  }
166 
167  /*
168  * typical clib idiom. Don't repeatedly allocate and free
169  * the per-neighbor rx buffer. Reset its apparent length to zero
170  * and reuse it.
171  */
172  if (sif->last_rx_pkt)
173  _vec_len (sif->last_rx_pkt) = 0;
174 
175  /*
176  * Make sure the per-neighbor rx buffer is big enough to hold
177  * the data we're about to copy
178  */
180 
181  /*
182  * Coalesce / copy the buffer chain into the per-neighbor
183  * rx buffer
184  */
185  nbytes = vlib_buffer_contents (vm, bi0, sif->last_rx_pkt);
186  ASSERT (nbytes <= vec_len (sif->last_rx_pkt));
187 
188  if (nbytes < sizeof (lacp_pdu_t))
189  {
190  return LACP_ERROR_TOO_SMALL;
191  }
192 
193  last_packet_signature =
194  hash_memory (sif->last_rx_pkt, vec_len (sif->last_rx_pkt), 0xd00b);
195 
197  if (sif->last_packet_signature_valid &&
198  (sif->last_packet_signature == last_packet_signature) &&
200  {
202  sif->ttl_in_seconds);
203  e = LACP_ERROR_CACHE_HIT;
204  }
205  else
206  {
207  /* Actually scan the packet */
208  e = lacp_packet_scan (vm, sif);
210  sif->last_packet_signature = last_packet_signature;
211  }
212 
213  if (sif->last_rx_pkt)
214  _vec_len (sif->last_rx_pkt) = 0;
215 
216  return e;
217 }
218 
219 /*
220  * setup neighbor hash table
221  */
222 static clib_error_t *
224 {
225  clib_error_t *error;
226 
227  if ((error = vlib_call_init_function (vm, lacp_periodic_init)))
228  return error;
229 
230  return 0;
231 }
232 
234 
235 /*
236  * packet trace format function, very similar to
237  * lacp_packet_scan except that we call the per TLV format
238  * functions instead of the per TLV processing functions
239  */
240 u8 *
241 lacp_input_format_trace (u8 * s, va_list * args)
242 {
243  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
244  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
245  lacp_input_trace_t *t = va_arg (*args, lacp_input_trace_t *);
246  lacp_pdu_t *lacpdu = &t->pkt.lacpdu;
247  marker_pdu_t *marker = &t->pkt.marker;
248  int i, len;
249  u8 *p;
250  lacp_state_struct *state_entry;
251 
253  t->sw_if_index);
254  s = format (s, "Length: %d\n", t->len);
255  if (t->len >= sizeof (lacp_pdu_t))
256  {
257  switch (lacpdu->subtype)
258  {
259  case MARKER_SUBTYPE:
260  if (marker->version_number == MARKER_PROTOCOL_VERSION)
261  s = format (s, " Markerv1\n");
262  else
263  s = format (s, " Subtype %u, Version %u\n", marker->subtype,
264  marker->version_number);
265  s = format (s, " Marker Information TLV: type %u\n",
266  marker->marker_info.tlv_type);
267  s = format (s, " Marker Information TLV: length %u\n",
268  marker->marker_info.tlv_length);
269  s = format (s, " Requester port: %u\n",
270  marker->marker_info.requester_port);
271  s = format (s, " Requester system: %U\n", format_ethernet_address,
272  marker->marker_info.requester_system);
273  s = format (s, " Requester transaction ID: %u\n",
274  marker->marker_info.requester_transaction_id);
275  break;
276 
277  case LACP_SUBTYPE:
278  if (lacpdu->version_number == LACP_ACTOR_LACP_VERSION)
279  s = format (s, " LACPv1\n");
280  else
281  s = format (s, " Subtype %u, Version %u\n", lacpdu->subtype,
282  lacpdu->version_number);
283  s = format (s, " Actor Information TLV: length %u\n",
284  lacpdu->actor.tlv_length);
285  s = format (s, " System %U\n", format_ethernet_address,
286  lacpdu->actor.port_info.system);
287  s = format (s, " System priority %u\n",
288  ntohs (lacpdu->actor.port_info.system_priority));
289  s = format (s, " Key %u\n", ntohs (lacpdu->actor.port_info.key));
290  s = format (s, " Port priority %u\n",
291  ntohs (lacpdu->actor.port_info.port_priority));
292  s = format (s, " Port number %u\n",
293  ntohs (lacpdu->actor.port_info.port_number));
294  s = format (s, " State 0x%x\n", lacpdu->actor.port_info.state);
295  state_entry = (lacp_state_struct *) & lacp_state_array;
296  while (state_entry->str)
297  {
298  if (lacpdu->actor.port_info.state & (1 << state_entry->bit))
299  s = format (s, " %s (%d)\n", state_entry->str,
300  state_entry->bit);
301  state_entry++;
302  }
303 
304  s = format (s, " Partner Information TLV: length %u\n",
305  lacpdu->partner.tlv_length);
306  s = format (s, " System %U\n", format_ethernet_address,
307  lacpdu->partner.port_info.system);
308  s = format (s, " System priority %u\n",
309  ntohs (lacpdu->partner.port_info.system_priority));
310  s =
311  format (s, " Key %u\n", ntohs (lacpdu->partner.port_info.key));
312  s =
313  format (s, " Port priority %u\n",
314  ntohs (lacpdu->partner.port_info.port_priority));
315  s =
316  format (s, " Port number %u\n",
317  ntohs (lacpdu->partner.port_info.port_number));
318  s = format (s, " State 0x%x\n", lacpdu->partner.port_info.state);
319  state_entry = (lacp_state_struct *) & lacp_state_array;
320  while (state_entry->str)
321  {
322  if (lacpdu->partner.port_info.state & (1 << state_entry->bit))
323  s = format (s, " %s (%d)\n", state_entry->str,
324  state_entry->bit);
325  state_entry++;
326  }
327  break;
328 
329  default:
330  break;
331  }
332  }
333 
334  if (t->len > sizeof (lacp_pdu_t))
335  len = sizeof (lacp_pdu_t);
336  else
337  len = t->len;
338  p = (u8 *) lacpdu;
339  for (i = 0; i < len; i++)
340  {
341  if ((i % 16) == 0)
342  {
343  if (i)
344  s = format (s, "\n");
345  s = format (s, " 0x%04x: ", i);
346  }
347  if ((i % 2) == 0)
348  s = format (s, " ");
349  s = format (s, "%02x", p[i]);
350  }
351 
352  return s;
353 }
354 
355 /*
356  * fd.io coding-style-patch-verification: ON
357  *
358  * Local Variables:
359  * eval: (c-set-style "gnu")
360  * End:
361  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:434
vlib_main_t * vlib_main
Definition: node.h:119
#define CLIB_UNUSED(x)
Definition: clib.h:79
static void send_ethernet_marker_response_pdu(slave_if_t *sif)
Definition: input.c:64
u8 last_packet_signature_valid
Definition: node.h:198
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static int lacp_packet_scan(vlib_main_t *vm, slave_if_t *sif)
Definition: input.c:21
u8 * last_marker_pkt
Definition: node.h:205
int i
lacp_state_struct lacp_state_array[]
Definition: node.c:21
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:107
u8 mode
Definition: node.h:279
format_function_t format_vnet_sw_if_index_name
static void marker_fill_pdu(marker_pdu_t *marker, slave_if_t *sif)
Definition: input.c:45
u8 * lacp_input_format_trace(u8 *s, va_list *args)
Definition: input.c:241
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:104
f32 ttl_in_seconds
Definition: node.h:184
marker_pdu_t marker
Definition: node.h:84
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:773
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
vnet_main_t * vnet_main
Definition: node.h:120
lacp_port_info_t actor
Definition: node.h:215
uword * active_slave_by_sw_if_index
Definition: node.h:161
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
static int handle_marker_protocol(vlib_main_t *vm, slave_if_t *sif)
Definition: input.c:114
#define vlib_call_init_function(vm, x)
Definition: init.h:162
u8 * last_rx_pkt
Definition: node.h:202
#define MARKER_SUBTYPE
Definition: protocol.h:128
#define hash_get(h, key)
Definition: hash.h:248
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
union lacp_input_trace_t::@419 pkt
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:191
#define LACP_SUBTYPE
Definition: protocol.h:25
#define MARKER_PROTOCOL_VERSION
Definition: protocol.h:129
static clib_error_t * lacp_periodic_init(vlib_main_t *vm)
Definition: lacp.c:207
static uword vlib_buffer_contents(vlib_main_t *vm, u32 buffer_index, u8 *contents)
Copy buffer contents to memory.
Definition: buffer_funcs.h:141
u32 marker_tx_id
Definition: node.h:272
u16 n_vectors
Definition: node.h:344
u32 sw_if_index
Definition: node.h:181
vlib_main_t * vm
Definition: buffer.c:294
lacp_error_t
Definition: node.h:69
#define clib_memcpy(a, b, c)
Definition: string.h:75
int rx_state
Definition: node.h:264
lacp_main_t lacp_main
Definition: lacp.c:25
#define ASSERT(truth)
lacp_pdu_t lacpdu
Definition: node.h:85
unsigned int u32
Definition: types.h:88
lacp_error_t lacp_input(vlib_main_t *vm, vlib_buffer_t *b0, u32 bi0)
Definition: input.c:135
static bond_if_t * bond_get_master_by_dev_instance(u32 dev_instance)
Definition: node.h:432
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:224
u32 bif_dev_instance
Definition: node.h:274
vlib_packet_template_t marker_packet_templates[MARKER_N_PACKET_TEMPLATES]
Definition: node.h:129
void marker_fill_request_pdu(marker_pdu_t *marker, slave_if_t *sif)
Definition: input.c:54
u64 uword
Definition: types.h:112
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:159
Definition: defs.h:47
lacp_machine_t lacp_rx_machine
Definition: rx_machine.c:108
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u32 sw_if_index
Definition: node.h:80
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
static void lacp_start_current_while_timer(vlib_main_t *vm, slave_if_t *sif, u8 expiration)
Definition: rx_machine.h:77
#define vnet_buffer(b)
Definition: buffer.h:372
u8 data[0]
Packet data.
Definition: buffer.h:179
static clib_error_t * lacp_init(vlib_main_t *vm)
Definition: input.c:223
static slave_if_t * bond_get_slave_by_sw_if_index(u32 sw_if_index)
Definition: node.h:440
uword last_packet_signature
Definition: node.h:199
u8 packet_template_index
Definition: node.h:193
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
int lacp_machine_dispatch(lacp_machine_t *machine, vlib_main_t *vm, slave_if_t *sif, int event, int *state)
Definition: lacp.c:286
Definition: defs.h:46
#define LACP_ACTOR_LACP_VERSION
Definition: protocol.h:26