FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
netlink.c
Go to the documentation of this file.
1 /*
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 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 
23 #include <linux/netlink.h>
24 #include <linux/rtnetlink.h>
25 
26 #include <vlib/vlib.h>
27 #include <vlib/unix/unix.h>
28 #include <vnet/devices/netlink.h>
29 
30 typedef struct
31 {
32  u8 *data;
34 
35 static void
37  void *msg_data, int msg_len)
38 {
39  struct nlmsghdr *nh;
40  u8 *p;
41  clib_memset (m, 0, sizeof (vnet_netlink_msg_t));
42  vec_add2 (m->data, p, NLMSG_SPACE (msg_len));
43  ASSERT (m->data == p);
44 
45  nh = (struct nlmsghdr *) p;
46  nh->nlmsg_flags = flags | NLM_F_ACK;
47  nh->nlmsg_type = type;
48  clib_memcpy (m->data + sizeof (struct nlmsghdr), msg_data, msg_len);
49 }
50 
51 static void
53  void *rta_data, int rta_data_len)
54 {
55  struct rtattr *rta;
56  u8 *p;
57 
58  vec_add2 (m->data, p, RTA_SPACE (rta_data_len));
59  rta = (struct rtattr *) p;
60  rta->rta_type = rta_type;
61  rta->rta_len = RTA_LENGTH (rta_data_len);
62  clib_memcpy (RTA_DATA (rta), rta_data, rta_data_len);
63 }
64 
65 static clib_error_t *
67 {
68  clib_error_t *err = 0;
69  struct sockaddr_nl ra = { 0 };
70  int len, sock;
71  struct nlmsghdr *nh = (struct nlmsghdr *) m->data;
72  nh->nlmsg_len = vec_len (m->data);
73  char buf[4096];
74 
75  if ((sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
76  return clib_error_return_unix (0, "socket(AF_NETLINK)");
77 
78  ra.nl_family = AF_NETLINK;
79  ra.nl_pid = 0;
80 
81  if ((bind (sock, (struct sockaddr *) &ra, sizeof (ra))) == -1)
82  {
83  err = clib_error_return_unix (0, "bind");
84  goto done;
85  }
86 
87  if ((send (sock, m->data, vec_len (m->data), 0)) == -1)
88  err = clib_error_return_unix (0, "send");
89 
90  if ((len = recv (sock, buf, sizeof (buf), 0)) == -1)
91  err = clib_error_return_unix (0, "recv");
92 
93  for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
94  nh = NLMSG_NEXT (nh, len))
95  {
96  if (nh->nlmsg_type == NLMSG_DONE)
97  goto done;
98 
99  if (nh->nlmsg_type == NLMSG_ERROR)
100  {
101  struct nlmsgerr *e = (struct nlmsgerr *) NLMSG_DATA (nh);
102  if (e->error)
103  err = clib_error_return (0, "netlink error %d", e->error);
104  goto done;
105  }
106  }
107 
108 done:
109  close (sock);
110  vec_free (m->data);
111  return err;
112 }
113 
114 clib_error_t *
115 vnet_netlink_set_link_name (int ifindex, char *new_ifname)
116 {
118  struct ifinfomsg ifmsg = { 0 };
119  clib_error_t *err = 0;
120 
121  ifmsg.ifi_index = ifindex;
122  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
123  &ifmsg, sizeof (struct ifinfomsg));
124 
125  vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
126  strlen (new_ifname) + 1);
127 
128  err = vnet_netlink_msg_send (&m);
129  if (err)
130  err = clib_error_return (0, "set link name %U", format_clib_error, err);
131  return err;
132 }
133 
134 clib_error_t *
135 vnet_netlink_set_link_netns (int ifindex, int netns_fd, char *new_ifname)
136 {
138  struct ifinfomsg ifmsg = { 0 };
139  clib_error_t *err = 0;
140 
141  ifmsg.ifi_index = ifindex;
142  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
143  &ifmsg, sizeof (struct ifinfomsg));
144 
145  vnet_netlink_msg_add_rtattr (&m, IFLA_NET_NS_FD, &netns_fd, sizeof (int));
146  if (new_ifname)
147  vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
148  strlen (new_ifname) + 1);
149 
150  err = vnet_netlink_msg_send (&m);
151  if (err)
152  err = clib_error_return (0, "set link netns %U", format_clib_error, err);
153  return err;
154 }
155 
156 clib_error_t *
157 vnet_netlink_set_link_master (int ifindex, char *master_ifname)
158 {
160  struct ifinfomsg ifmsg = { 0 };
161  int i;
162  clib_error_t *err = 0;
163 
164  ifmsg.ifi_index = ifindex;
165 
166  if ((i = if_nametoindex (master_ifname)) == 0)
167  clib_error_return_unix (0, "unknown master interface '%s'",
168  master_ifname);
169 
170  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
171  &ifmsg, sizeof (struct ifinfomsg));
172  vnet_netlink_msg_add_rtattr (&m, IFLA_MASTER, &i, sizeof (int));
173  err = vnet_netlink_msg_send (&m);
174  if (err)
175  err = clib_error_return (0, "set link master %U", format_clib_error, err);
176  return err;
177 }
178 
179 clib_error_t *
181 {
183  struct ifinfomsg ifmsg = { 0 };
184  clib_error_t *err = 0;
185 
186  ifmsg.ifi_index = ifindex;
187 
188  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
189  &ifmsg, sizeof (struct ifinfomsg));
190  vnet_netlink_msg_add_rtattr (&m, IFLA_ADDRESS, mac, 6);
191  err = vnet_netlink_msg_send (&m);
192  if (err)
193  err = clib_error_return (0, "set link addr %U", format_clib_error, err);
194  return err;
195 }
196 
197 clib_error_t *
198 vnet_netlink_set_link_state (int ifindex, int up)
199 {
201  struct ifinfomsg ifmsg = { 0 };
202  clib_error_t *err = 0;
203 
204  ifmsg.ifi_flags = ((up) ? IFF_UP : 0);
205  ifmsg.ifi_change = IFF_UP;
206  ifmsg.ifi_index = ifindex;
207 
208  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
209  &ifmsg, sizeof (struct ifinfomsg));
210  err = vnet_netlink_msg_send (&m);
211  if (err)
212  err = clib_error_return (0, "set link state %U", format_clib_error, err);
213  return err;
214 }
215 
216 clib_error_t *
217 vnet_netlink_set_link_mtu (int ifindex, int mtu)
218 {
220  struct ifinfomsg ifmsg = { 0 };
221  clib_error_t *err = 0;
222 
223  ifmsg.ifi_index = ifindex;
224 
225  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
226  &ifmsg, sizeof (struct ifinfomsg));
227  vnet_netlink_msg_add_rtattr (&m, IFLA_MTU, &mtu, sizeof (int));
228  err = vnet_netlink_msg_send (&m);
229  if (err)
230  err = clib_error_return (0, "set link mtu %U", format_clib_error, err);
231  return err;
232 }
233 
234 clib_error_t *
235 vnet_netlink_add_ip4_addr (int ifindex, void *addr, int pfx_len)
236 {
238  struct ifaddrmsg ifa = { 0 };
239  clib_error_t *err = 0;
240 
241  ifa.ifa_family = AF_INET;
242  ifa.ifa_prefixlen = pfx_len;
243  ifa.ifa_index = ifindex;
244 
245  vnet_netlink_msg_init (&m, RTM_NEWADDR,
246  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
247  &ifa, sizeof (struct ifaddrmsg));
248 
249  vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 4);
250  vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 4);
251  err = vnet_netlink_msg_send (&m);
252  if (err)
253  err = clib_error_return (0, "add ip4 addr %U", format_clib_error, err);
254  return err;
255 }
256 
257 clib_error_t *
258 vnet_netlink_add_ip6_addr (int ifindex, void *addr, int pfx_len)
259 {
261  struct ifaddrmsg ifa = { 0 };
262  clib_error_t *err = 0;
263 
264  ifa.ifa_family = AF_INET6;
265  ifa.ifa_prefixlen = pfx_len;
266  ifa.ifa_index = ifindex;
267 
268  vnet_netlink_msg_init (&m, RTM_NEWADDR,
269  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
270  &ifa, sizeof (struct ifaddrmsg));
271 
272  vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 16);
273  vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 16);
274  err = vnet_netlink_msg_send (&m);
275  if (err)
276  err = clib_error_return (0, "add ip6 addr %U", format_clib_error, err);
277  return err;
278 }
279 
280 clib_error_t *
281 vnet_netlink_add_ip4_route (void *dst, u8 dst_len, void *gw)
282 {
284  struct rtmsg rtm = { 0 };
285  u8 dflt[4] = { 0 };
286  clib_error_t *err = 0;
287 
288  rtm.rtm_family = AF_INET;
289  rtm.rtm_table = RT_TABLE_MAIN;
290  rtm.rtm_type = RTN_UNICAST;
291  rtm.rtm_dst_len = dst_len;
292 
293  vnet_netlink_msg_init (&m, RTM_NEWROUTE,
294  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
295  &rtm, sizeof (struct rtmsg));
296 
297  vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 4);
298  vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 4);
299  err = vnet_netlink_msg_send (&m);
300  if (err)
301  err = clib_error_return (0, "add ip4 route %U", format_clib_error, err);
302  return err;
303 }
304 
305 clib_error_t *
306 vnet_netlink_add_ip6_route (void *dst, u8 dst_len, void *gw)
307 {
309  struct rtmsg rtm = { 0 };
310  u8 dflt[16] = { 0 };
311  clib_error_t *err = 0;
312 
313  rtm.rtm_family = AF_INET6;
314  rtm.rtm_table = RT_TABLE_MAIN;
315  rtm.rtm_type = RTN_UNICAST;
316  rtm.rtm_dst_len = dst_len;
317 
318  vnet_netlink_msg_init (&m, RTM_NEWROUTE,
319  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
320  &rtm, sizeof (struct rtmsg));
321 
322  vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 16);
323  vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 16);
324  err = vnet_netlink_msg_send (&m);
325  if (err)
326  err = clib_error_return (0, "add ip6 route %U", format_clib_error, err);
327  return err;
328 }
329 
330 /*
331  * fd.io coding-style-patch-verification: ON
332  *
333  * Local Variables:
334  * eval: (c-set-style "gnu")
335  * End:
336  */
u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
vl_api_mac_address_t mac
Definition: l2.api:502
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
vhost_vring_addr_t addr
Definition: vhost_user.h:111
unsigned char u8
Definition: types.h:56
#define clib_memcpy(d, s, n)
Definition: string.h:180
#define clib_error_return(e, args...)
Definition: error.h:99
vl_api_fib_path_type_t type
Definition: fib_types.api:123
unsigned short u16
Definition: types.h:57
#define clib_error_return_unix(e, args...)
Definition: error.h:102
vl_api_address_t dst
Definition: gre.api:55
u8 len
Definition: ip_types.api:92
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define ASSERT(truth)
unsigned int if_nametoindex(const char *ifname)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)