FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
lldp_output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2016 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  * @file
17  * @brief LLDP packet generation implementation
18  */
19 #include <lldp/lldp_node.h>
20 
21 static void
22 lldp_build_mgmt_addr_tlv (u8 ** t0p, u8 subtype, u8 addr_len, u8 * addr,
23  u32 if_index, u8 oid_len, u8 * oid)
24 {
25  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
26 
27  lldp_tlv_set_code (t, LLDP_TLV_NAME (mgmt_addr));
28  t->v[0] = addr_len + 1; /* address string length */
29  t->v[1] = subtype; /* address subtype */
30  clib_memcpy_fast (&(t->v[2]), addr, addr_len); /* address */
31  t->v[addr_len + 2] = 2; /* interface numbering subtype: ifIndex */
32  t->v[addr_len + 3] = (if_index >> 24) & 0xFF; /* interface number */
33  t->v[addr_len + 4] = (if_index >> 16) & 0xFF;
34  t->v[addr_len + 5] = (if_index >> 8) & 0xFF;
35  t->v[addr_len + 6] = (if_index >> 0) & 0xFF;
36  t->v[addr_len + 7] = oid_len; /* OID string length */
37 
38  if (oid_len > 0)
39  clib_memcpy_fast ((u8 *) & (t->v[addr_len + 8]), oid, oid_len);
40 
41  lldp_tlv_set_length (t, addr_len + oid_len + 8);
42  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + addr_len + oid_len + 8;
43 }
44 
45 static void
47 {
48  lldp_chassis_id_tlv_t *t = (lldp_chassis_id_tlv_t *) * t0p;
49 
50  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (chassis_id));
51  t->subtype = LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr);
52 
53  const size_t addr_len = 6;
54  clib_memcpy_fast (&t->id, hw->hw_address, addr_len);
55  const size_t len =
56  STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + addr_len;
57  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
58  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
59 }
60 
61 static void
63 {
64  lldp_port_id_tlv_t *t = (lldp_port_id_tlv_t *) * t0p;
65 
66  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (port_id));
67  t->subtype = LLDP_PORT_ID_SUBTYPE_NAME (intf_name);
68 
69  const size_t name_len = vec_len (hw->name);
70  clib_memcpy_fast (&t->id, hw->name, name_len);
71  const size_t len = STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) + name_len;
72  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
73  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
74 }
75 
76 static void
77 lldp_add_ttl (const lldp_main_t * lm, u8 ** t0p, int shutdown)
78 {
79  lldp_ttl_tlv_t *t = (lldp_ttl_tlv_t *) * t0p;
80  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (ttl));
81  if (shutdown)
82  {
83  t->ttl = 0;
84  }
85  else
86  {
87  if ((size_t) lm->msg_tx_interval * lm->msg_tx_hold + 1 > (1 << 16) - 1)
88  {
89  t->ttl = htons ((1 << 16) - 1);
90  }
91  else
92  {
93  t->ttl = htons (lm->msg_tx_hold * lm->msg_tx_interval + 1);
94  }
95  }
96  const size_t len = STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl);
97  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
98  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
99 }
100 
101 static void
102 lldp_add_port_desc (const lldp_main_t * lm, lldp_intf_t * n, u8 ** t0p)
103 {
104  const size_t len = vec_len (n->port_desc);
105  if (len)
106  {
107  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
108  lldp_tlv_set_code (t, LLDP_TLV_NAME (port_desc));
110  clib_memcpy_fast (t->v, n->port_desc, len);
111  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
112  }
113 }
114 
115 static void
116 lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p)
117 {
118  const size_t len = vec_len (lm->sys_name);
119  if (len)
120  {
121  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
122  lldp_tlv_set_code (t, LLDP_TLV_NAME (sys_name));
124  clib_memcpy_fast (t->v, lm->sys_name, len);
125  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
126  }
127 }
128 
129 static void
131  u8 ** t0p)
132 {
133  const size_t len_ip4 = vec_len (n->mgmt_ip4);
134  const size_t len_ip6 = vec_len (n->mgmt_ip6);
135 
136  if (!(len_ip4 | len_ip6))
137  {
138  /*
139  If no management address is configured, the interface port's MAC
140  address is sent in one TLV.
141  */
142 
143  lldp_build_mgmt_addr_tlv (t0p, 1, /* address subtype: Ipv4 */
144  6, /* address string length */
145  hw->hw_address, /* address */
146  hw->hw_if_index, /* if index */
147  vec_len (n->mgmt_oid), /* OID length */
148  n->mgmt_oid); /* OID */
149  return;
150  }
151 
152  if (len_ip4)
153  {
154  lldp_build_mgmt_addr_tlv (t0p, 1, /* address subtype: Ipv4 */
155  len_ip4, /* address string length */
156  n->mgmt_ip4, /* address */
157  hw->hw_if_index, /* if index */
158  vec_len (n->mgmt_oid), /* OID length */
159  n->mgmt_oid); /* OID */
160  }
161 
162  if (len_ip6)
163  {
164  lldp_build_mgmt_addr_tlv (t0p, 2, /* address subtype: Ipv6 */
165  len_ip6, /* address string length */
166  n->mgmt_ip6, /* address */
167  hw->hw_if_index, /* if index */
168  vec_len (n->mgmt_oid), /* OID length */
169  n->mgmt_oid); /* OID */
170  }
171 }
172 
173 static void
175 {
176  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
177  lldp_tlv_set_code (t, LLDP_TLV_NAME (pdu_end));
178  lldp_tlv_set_length (t, 0);
179  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head);
180 }
181 
182 static void
184  int shutdown, lldp_intf_t * n)
185 {
186  lldp_add_chassis_id (hw, t0p);
187  lldp_add_port_id (hw, t0p);
188  lldp_add_ttl (lm, t0p, shutdown);
189  lldp_add_port_desc (lm, n, t0p);
190  lldp_add_sys_name (lm, t0p);
191  lldp_add_mgmt_addr (n, hw, t0p);
192  lldp_add_pdu_end (t0p);
193 }
194 
195 /*
196  * send a lldp pkt on an ethernet interface
197  */
198 void
199 lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown)
200 {
201  u32 *to_next;
202  ethernet_header_t *h0;
204  u32 bi0;
205  vlib_buffer_t *b0;
206  u8 *t0;
207  vlib_frame_t *f;
208  vlib_main_t *vm = lm->vlib_main;
209  vnet_main_t *vnm = lm->vnet_main;
210 
211  /*
212  * see lldp_template_init() to understand what's already painted
213  * into the buffer by the packet template mechanism
214  */
216 
217  if (!h0)
218  return;
219 
220  /* Add the interface's ethernet source address */
221  hw = vnet_get_hw_interface (vnm, n->hw_if_index);
222 
224  vec_len (hw->hw_address));
225 
226  u8 *data = ((u8 *) h0) + sizeof (*h0);
227  t0 = data;
228 
229  /* add TLVs */
230  lldp_add_tlvs (lm, hw, &t0, shutdown, n);
231 
232  /* Set the outbound packet length */
233  b0 = vlib_get_buffer (vm, bi0);
234  b0->current_length = sizeof (*h0) + t0 - data;
235 
236  /* And the outbound interface */
237  vnet_buffer (b0)->sw_if_index[VLIB_TX] = hw->sw_if_index;
238 
239  /* And output the packet on the correct interface */
241  to_next = vlib_frame_vector_args (f);
242  to_next[0] = bi0;
243  f->n_vectors = 1;
244 
246  n->last_sent = vlib_time_now (vm);
247 }
248 
249 void
251 {
252  if (n)
253  {
254  lldp_unschedule_intf (lm, n);
256  vec_free (n->chassis_id);
257  vec_free (n->port_id);
258  vec_free (n->port_desc);
259  vec_free (n->mgmt_ip4);
260  vec_free (n->mgmt_ip6);
261  vec_free (n->mgmt_oid);
262  pool_put (lm->intfs, n);
263  }
264 }
265 
266 
267 /* 01:80:C2:00:00:0E - propagation constrained to a single
268  * physical link - stopped by all type of bridge */
269 const u8 lldp_mac_addr[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0E };
270 
271 static clib_error_t *
273 {
274  lldp_main_t *lm = &lldp_main;
275 
276  /* Create the ethernet lldp packet template */
277  {
279 
280  clib_memset (&h, 0, sizeof (h));
281 
282  h.dst_address[0] = lldp_mac_addr[0];
283  h.dst_address[1] = lldp_mac_addr[1];
284  h.dst_address[2] = lldp_mac_addr[2];
285  h.dst_address[3] = lldp_mac_addr[3];
286  h.dst_address[4] = lldp_mac_addr[4];
287  h.dst_address[5] = lldp_mac_addr[5];
288 
289  /* leave src address blank (fill in at send time) */
290 
291  h.type = htons (ETHERNET_TYPE_802_1_LLDP);
292 
294  /* data */ &h, sizeof (h),
295  /* alloc chunk size */ 8, "lldp-ethernet");
296  }
297 
298  return 0;
299 }
300 
302 
303 /*
304  * fd.io coding-style-patch-verification: ON
305  *
306  * Local Variables:
307  * eval: (c-set-style "gnu")
308  * End:
309  */
vlib_frame_t::n_vectors
u16 n_vectors
Definition: node.h:387
lldp_add_tlvs
static void lldp_add_tlvs(lldp_main_t *lm, vnet_hw_interface_t *hw, u8 **t0p, int shutdown, lldp_intf_t *n)
Definition: lldp_output.c:183
lldp_main_t::intf_by_hw_if_index
uword * intf_by_hw_if_index
Definition: lldp_node.h:65
lldp_intf::chassis_id
u8 * chassis_id
Definition: lldp_node.h:40
lldp_main_t::msg_tx_interval
u16 msg_tx_interval
Definition: lldp_node.h:102
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
f
vlib_frame_t * f
Definition: interface_output.c:1098
lldp_main_t::sys_name
u8 * sys_name
Definition: lldp_node.h:84
ttl
u8 ttl
Definition: fib_types.api:26
vnet_hw_interface_t::hw_address
u8 * hw_address
Definition: interface.h:649
vnet_hw_interface_t::sw_if_index
u32 sw_if_index
Definition: interface.h:670
lldp_intf::port_id
u8 * port_id
Definition: lldp_node.h:41
ethernet_header_t::src_address
u8 src_address[6]
Definition: packet.h:56
lldp_main_t::vlib_main
vlib_main_t * vlib_main
Definition: lldp_node.h:80
lldp_build_mgmt_addr_tlv
static void lldp_build_mgmt_addr_tlv(u8 **t0p, u8 subtype, u8 addr_len, u8 *addr, u32 if_index, u8 oid_len, u8 *oid)
Definition: lldp_output.c:22
lldp_add_pdu_end
static void lldp_add_pdu_end(u8 **t0p)
Definition: lldp_output.c:174
LLDP_CHASS_ID_SUBTYPE_NAME
#define LLDP_CHASS_ID_SUBTYPE_NAME(t)
Definition: lldp_protocol.h:81
lldp_unschedule_intf
void lldp_unschedule_intf(lldp_main_t *lm, lldp_intf_t *n)
Definition: lldp_node.c:267
lldp_intf::mgmt_ip4
u8 * mgmt_ip4
Definition: lldp_node.h:50
LLDP_TLV_NAME
#define LLDP_TLV_NAME(t)
Definition: lldp_protocol.h:44
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
lldp_add_port_desc
static void lldp_add_port_desc(const lldp_main_t *lm, lldp_intf_t *n, u8 **t0p)
Definition: lldp_output.c:102
lldp_intf::last_sent
f64 last_sent
Definition: lldp_node.h:37
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
vlib_frame_t
Definition: node.h:372
vlib_get_frame_to_node
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
h
h
Definition: flowhash_template.h:372
hash_unset
#define hash_unset(h, key)
Definition: hash.h:261
lldp_main_t::msg_tx_hold
u8 msg_tx_hold
Definition: lldp_node.h:93
vlib_put_frame_to_node
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
lldp_main_t
Definition: lldp_node.h:59
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
len
u8 len
Definition: ip_types.api:103
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vnet_get_hw_interface
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:44
lldp_add_port_id
static void lldp_add_port_id(const vnet_hw_interface_t *hw, u8 **t0p)
Definition: lldp_output.c:62
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
lldp_tlv_set_length
void lldp_tlv_set_length(lldp_tlv_t *tlv, u16 length)
Definition: lldp_input.c:104
ethernet_header_t
Definition: packet.h:52
lldp_mac_addr
const u8 lldp_mac_addr[6]
Definition: lldp_output.c:269
lldp_intf::mgmt_oid
u8 * mgmt_oid
Definition: lldp_node.h:56
lldp_template_init
static clib_error_t * lldp_template_init(vlib_main_t *vm)
Definition: lldp_output.c:272
lldp_main
lldp_main_t lldp_main
Definition: lldp_input.c:117
lldp_tlv_set_code
void lldp_tlv_set_code(lldp_tlv_t *tlv, lldp_tlv_code_t code)
Definition: lldp_input.c:92
lldp_intf::mgmt_ip6
u8 * mgmt_ip6
Definition: lldp_node.h:53
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
mac_addr
vl_api_mac_address_t mac_addr
Definition: l2.api:210
data
u8 data[128]
Definition: ipsec_types.api:95
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
vlib_packet_template_get_packet
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:377
lldp_add_mgmt_addr
static void lldp_add_mgmt_addr(const lldp_intf_t *n, const vnet_hw_interface_t *hw, u8 **t0p)
Definition: lldp_output.c:130
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
LLDP_PORT_ID_SUBTYPE_NAME
#define LLDP_PORT_ID_SUBTYPE_NAME(t)
Definition: lldp_protocol.h:110
lldp_intf::port_desc
u8 * port_desc
Definition: lldp_node.h:47
lldp_node.h
LLDP global declarations.
lldp_add_ttl
static void lldp_add_ttl(const lldp_main_t *lm, u8 **t0p, int shutdown)
Definition: lldp_output.c:77
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
vnet_hw_interface_t::output_node_index
u32 output_node_index
Definition: interface.h:653
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
lldp_intf::hw_if_index
u32 hw_if_index
Definition: lldp_node.h:33
lldp_add_sys_name
static void lldp_add_sys_name(const lldp_main_t *lm, u8 **t0p)
Definition: lldp_output.c:116
vnet_hw_interface_t::name
u8 * name
Definition: interface.h:678
vnet_hw_interface_t::hw_if_index
u32 hw_if_index
Definition: interface.h:667
vlib_packet_template_init
void vlib_packet_template_init(vlib_main_t *vm, vlib_packet_template_t *t, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_alloc, char *fmt,...)
Definition: buffer.c:355
lldp_main_t::intfs
lldp_intf_t * intfs
Definition: lldp_node.h:62
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
lldp_add_chassis_id
static void lldp_add_chassis_id(const vnet_hw_interface_t *hw, u8 **t0p)
Definition: lldp_output.c:46
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
lldp_send_ethernet
void lldp_send_ethernet(lldp_main_t *lm, lldp_intf_t *n, int shutdown)
Definition: lldp_output.c:199
STRUCT_SIZE_OF
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:75
lldp_main_t::vnet_main
vnet_main_t * vnet_main
Definition: lldp_node.h:81
lldp_delete_intf
void lldp_delete_intf(lldp_main_t *lm, lldp_intf_t *n)
Definition: lldp_output.c:250
lldp_main_t::packet_template
vlib_packet_template_t packet_template
Definition: lldp_node.h:77
lldp_intf
Definition: lldp_node.h:30
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111