FD.io VPP  v17.04.2-2-ga8f93f8
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 <vnet/lldp/lldp_node.h>
20 
21 static void
23 {
24  lldp_chassis_id_tlv_t *t = (lldp_chassis_id_tlv_t *) * t0p;
25 
26  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (chassis_id));
27  t->subtype = LLDP_CHASS_ID_SUBTYPE_NAME (mac_addr);
28 
29  const size_t addr_len = 6;
30  clib_memcpy (&t->id, hw->hw_address, addr_len);
31  const size_t len =
32  STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) + addr_len;
33  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
34  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
35 }
36 
37 static void
39 {
40  lldp_port_id_tlv_t *t = (lldp_port_id_tlv_t *) * t0p;
41 
42  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (port_id));
43  t->subtype = LLDP_PORT_ID_SUBTYPE_NAME (intf_name);
44 
45  const size_t name_len = vec_len (hw->name);
46  clib_memcpy (&t->id, hw->name, name_len);
47  const size_t len = STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) + name_len;
48  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
49  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
50 }
51 
52 static void
53 lldp_add_ttl (const lldp_main_t * lm, u8 ** t0p, int shutdown)
54 {
55  lldp_ttl_tlv_t *t = (lldp_ttl_tlv_t *) * t0p;
56  lldp_tlv_set_code ((lldp_tlv_t *) t, LLDP_TLV_NAME (ttl));
57  if (shutdown)
58  {
59  t->ttl = 0;
60  }
61  else
62  {
63  if ((size_t) lm->msg_tx_interval * lm->msg_tx_hold + 1 > (1 << 16) - 1)
64  {
65  t->ttl = htons ((1 << 16) - 1);
66  }
67  else
68  {
69  t->ttl = htons (lm->msg_tx_hold * lm->msg_tx_interval + 1);
70  }
71  }
72  const size_t len = STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl);
73  lldp_tlv_set_length ((lldp_tlv_t *) t, len);
74  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
75 }
76 
77 static void
78 lldp_add_sys_name (const lldp_main_t * lm, u8 ** t0p)
79 {
80  const size_t len = vec_len (lm->sys_name);
81  if (len)
82  {
83  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
84  lldp_tlv_set_code (t, LLDP_TLV_NAME (sys_name));
85  lldp_tlv_set_length (t, len);
86  clib_memcpy (t->v, lm->sys_name, len);
87  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head) + len;
88  }
89 }
90 
91 static void
93 {
94  lldp_tlv_t *t = (lldp_tlv_t *) * t0p;
95  lldp_tlv_set_code (t, LLDP_TLV_NAME (pdu_end));
96  lldp_tlv_set_length (t, 0);
97  *t0p += STRUCT_SIZE_OF (lldp_tlv_t, head);
98 }
99 
100 static void
102  int shutdown)
103 {
104  lldp_add_chassis_id (hw, t0p);
105  lldp_add_port_id (hw, t0p);
106  lldp_add_ttl (lm, t0p, shutdown);
107  lldp_add_sys_name (lm, t0p);
108  lldp_add_pdu_end (t0p);
109 }
110 
111 /*
112  * send a lldp pkt on an ethernet interface
113  */
114 void
115 lldp_send_ethernet (lldp_main_t * lm, lldp_intf_t * n, int shutdown)
116 {
117  u32 *to_next;
118  ethernet_header_t *h0;
120  u32 bi0;
121  vlib_buffer_t *b0;
122  u8 *t0;
123  vlib_frame_t *f;
124  vlib_main_t *vm = lm->vlib_main;
125  vnet_main_t *vnm = lm->vnet_main;
126 
127  /*
128  * see lldp_template_init() to understand what's already painted
129  * into the buffer by the packet template mechanism
130  */
131  h0 = vlib_packet_template_get_packet (vm, &lm->packet_template, &bi0);
132 
133  /* Add the interface's ethernet source address */
134  hw = vnet_get_hw_interface (vnm, n->hw_if_index);
135 
137 
138  u8 *data = ((u8 *) h0) + sizeof (*h0);
139  t0 = data;
140 
141  /* add TLVs */
142  lldp_add_tlvs (lm, hw, &t0, shutdown);
143 
144  /* Set the outbound packet length */
145  b0 = vlib_get_buffer (vm, bi0);
146  b0->current_length = sizeof (*h0) + t0 - data;
147 
148  /* And the outbound interface */
149  vnet_buffer (b0)->sw_if_index[VLIB_TX] = hw->sw_if_index;
150 
151  /* And output the packet on the correct interface */
153  to_next = vlib_frame_vector_args (f);
154  to_next[0] = bi0;
155  f->n_vectors = 1;
156 
158  n->last_sent = vlib_time_now (vm);
159 }
160 
161 void
163 {
164  if (n)
165  {
166  lldp_unschedule_intf (lm, n);
168  vec_free (n->chassis_id);
169  vec_free (n->port_id);
170  pool_put (lm->intfs, n);
171  }
172 }
173 
174 static clib_error_t *
176 {
177  lldp_main_t *lm = &lldp_main;
178 
179  /* Create the ethernet lldp packet template */
180  {
182 
183  memset (&h, 0, sizeof (h));
184 
185  /*
186  * Send to 01:80:C2:00:00:0E - propagation constrained to a single
187  * physical link - stopped by all type of bridge
188  */
189  h.dst_address[0] = 0x01;
190  h.dst_address[1] = 0x80;
191  h.dst_address[2] = 0xC2;
192  /* h.dst_address[3] = 0x00; (memset) */
193  /* h.dst_address[4] = 0x00; (memset) */
194  h.dst_address[5] = 0x0E;
195 
196  /* leave src address blank (fill in at send time) */
197 
198  h.type = htons (ETHERNET_TYPE_802_1_LLDP);
199 
201  /* data */ &h, sizeof (h),
202  /* alloc chunk size */ 8, "lldp-ethernet");
203  }
204 
205  return 0;
206 }
207 
209 
210 /*
211  * fd.io coding-style-patch-verification: ON
212  *
213  * Local Variables:
214  * eval: (c-set-style "gnu")
215  * End:
216  */
lldp_main_t lldp_main
Definition: lldp_input.c:117
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
vnet_main_t * vnet_main
Definition: lldp_node.h:70
u32 hw_if_index
Definition: lldp_node.h:33
#define LLDP_CHASS_ID_SUBTYPE_NAME(t)
Definition: lldp_protocol.h:81
#define hash_unset(h, key)
Definition: hash.h:260
u8 * chassis_id
Definition: lldp_node.h:40
lldp_intf_t * intfs
Definition: lldp_node.h:51
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:185
u8 src_address[6]
Definition: packet.h:54
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
f64 last_sent
Definition: lldp_node.h:37
static void lldp_add_tlvs(lldp_main_t *lm, vnet_hw_interface_t *hw, u8 **t0p, int shutdown)
Definition: lldp_output.c:101
u8 msg_tx_hold
Definition: lldp_node.h:82
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:818
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u8 * port_id
Definition: lldp_node.h:41
u8 dst_address[6]
Definition: packet.h:53
void lldp_tlv_set_code(lldp_tlv_t *tlv, lldp_tlv_code_t code)
Definition: lldp_input.c:92
static void lldp_add_ttl(const lldp_main_t *lm, u8 **t0p, int shutdown)
Definition: lldp_output.c:53
void lldp_send_ethernet(lldp_main_t *lm, lldp_intf_t *n, int shutdown)
Definition: lldp_output.c:115
static void lldp_add_sys_name(const lldp_main_t *lm, u8 **t0p)
Definition: lldp_output.c:78
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
u16 msg_tx_interval
Definition: lldp_node.h:91
uword * intf_by_hw_if_index
Definition: lldp_node.h:54
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
static void lldp_add_chassis_id(const vnet_hw_interface_t *hw, u8 **t0p)
Definition: lldp_output.c:22
void lldp_tlv_set_length(lldp_tlv_t *tlv, u16 length)
Definition: lldp_input.c:104
#define LLDP_PORT_ID_SUBTYPE_NAME(t)
void lldp_delete_intf(lldp_main_t *lm, lldp_intf_t *n)
Definition: lldp_output.c:162
u16 n_vectors
Definition: node.h:344
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
#define clib_memcpy(a, b, c)
Definition: string.h:69
unsigned int u32
Definition: types.h:88
static void lldp_add_pdu_end(u8 **t0p)
Definition: lldp_output.c:92
vlib_main_t * vlib_main
Definition: lldp_node.h:69
Definition: defs.h:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
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_physmem_alloc, char *fmt,...)
Definition: buffer.c:768
void lldp_unschedule_intf(lldp_main_t *lm, lldp_intf_t *n)
Definition: lldp_node.c:267
#define vnet_buffer(b)
Definition: buffer.h:294
LLDP global declarations.
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:64
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
vlib_packet_template_t packet_template
Definition: lldp_node.h:66
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
u8 * sys_name
Definition: lldp_node.h:73
static clib_error_t * lldp_template_init(vlib_main_t *vm)
Definition: lldp_output.c:175
static void lldp_add_port_id(const vnet_hw_interface_t *hw, u8 **t0p)
Definition: lldp_output.c:38
#define LLDP_TLV_NAME(t)
Definition: lldp_protocol.h:44