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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
18 #include <sys/types.h>
24 #include <linux/netlink.h>
25 #include <linux/rtnetlink.h>
27 #include <netlink/netlink.h>
28 #include <netlink/netlink_route.h>
31 #include <vlib/vlib.h>
32 #include <vlib/unix/unix.h>
33 #include <vnet/devices/netlink.h>
41 vnet_netlink_msg_init (vnet_netlink_msg_t * m, u16 type, u16 flags,
42 void *msg_data, int msg_len)
46 clib_memset (m, 0, sizeof (vnet_netlink_msg_t));
47 vec_add2 (m->data, p, NLMSG_SPACE (msg_len));
48 ASSERT (m->data == p);
50 nh = (struct nlmsghdr *) p;
51 nh->nlmsg_flags = flags | NLM_F_ACK;
52 nh->nlmsg_type = type;
53 clib_memcpy (m->data + sizeof (struct nlmsghdr), msg_data, msg_len);
57 vnet_netlink_msg_add_rtattr (vnet_netlink_msg_t * m, u16 rta_type,
58 void *rta_data, int rta_data_len)
63 vec_add2 (m->data, p, RTA_SPACE (rta_data_len));
64 rta = (struct rtattr *) p;
65 rta->rta_type = rta_type;
66 rta->rta_len = RTA_LENGTH (rta_data_len);
67 clib_memcpy (RTA_DATA (rta), rta_data, rta_data_len);
71 vnet_netlink_msg_send (vnet_netlink_msg_t *m, vnet_netlink_msg_t **replies)
73 clib_error_t *err = 0;
74 struct sockaddr_nl ra = { 0 };
76 struct nlmsghdr *nh = (struct nlmsghdr *) m->data;
77 nh->nlmsg_len = vec_len (m->data);
80 if ((sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
81 return clib_error_return_unix (0, "socket(AF_NETLINK)");
83 ra.nl_family = AF_NETLINK;
86 if ((bind (sock, (struct sockaddr *) &ra, sizeof (ra))) == -1)
88 err = clib_error_return_unix (0, "bind");
92 if ((send (sock, m->data, vec_len (m->data), 0)) == -1)
93 err = clib_error_return_unix (0, "send");
95 if ((len = recv (sock, buf, sizeof (buf), 0)) == -1)
96 err = clib_error_return_unix (0, "recv");
98 for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
99 nh = NLMSG_NEXT (nh, len))
101 if (nh->nlmsg_type == NLMSG_DONE)
104 if (nh->nlmsg_type == NLMSG_ERROR)
106 struct nlmsgerr *e = (struct nlmsgerr *) NLMSG_DATA (nh);
108 err = clib_error_return (0, "netlink error %d", e->error);
114 vnet_netlink_msg_t msg = { NULL };
116 vec_add2 (msg.data, p, nh->nlmsg_len);
117 clib_memcpy (p, nh, nh->nlmsg_len);
118 vec_add1 (*replies, msg);
129 vnet_netlink_set_link_name (int ifindex, char *new_ifname)
131 vnet_netlink_msg_t m;
132 struct ifinfomsg ifmsg = { 0 };
133 clib_error_t *err = 0;
135 ifmsg.ifi_index = ifindex;
136 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
137 &ifmsg, sizeof (struct ifinfomsg));
139 vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
140 strlen (new_ifname) + 1);
142 err = vnet_netlink_msg_send (&m, NULL);
144 err = clib_error_return (0, "set link name %U", format_clib_error, err);
149 vnet_netlink_set_link_netns (int ifindex, int netns_fd, char *new_ifname)
151 vnet_netlink_msg_t m;
152 struct ifinfomsg ifmsg = { 0 };
153 clib_error_t *err = 0;
155 ifmsg.ifi_index = ifindex;
156 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
157 &ifmsg, sizeof (struct ifinfomsg));
159 vnet_netlink_msg_add_rtattr (&m, IFLA_NET_NS_FD, &netns_fd, sizeof (int));
161 vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
162 strlen (new_ifname) + 1);
164 err = vnet_netlink_msg_send (&m, NULL);
166 err = clib_error_return (0, "set link netns %U", format_clib_error, err);
171 vnet_netlink_set_link_master (int ifindex, char *master_ifname)
173 vnet_netlink_msg_t m;
174 struct ifinfomsg ifmsg = { 0 };
176 clib_error_t *err = 0;
178 ifmsg.ifi_index = ifindex;
180 if ((i = if_nametoindex (master_ifname)) == 0)
181 clib_error_return_unix (0, "unknown master interface '%s'",
184 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
185 &ifmsg, sizeof (struct ifinfomsg));
186 vnet_netlink_msg_add_rtattr (&m, IFLA_MASTER, &i, sizeof (int));
187 err = vnet_netlink_msg_send (&m, NULL);
189 err = clib_error_return (0, "set link master %U", format_clib_error, err);
194 vnet_netlink_set_link_addr (int ifindex, u8 * mac)
196 vnet_netlink_msg_t m;
197 struct ifinfomsg ifmsg = { 0 };
198 clib_error_t *err = 0;
200 ifmsg.ifi_index = ifindex;
202 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
203 &ifmsg, sizeof (struct ifinfomsg));
204 vnet_netlink_msg_add_rtattr (&m, IFLA_ADDRESS, mac, 6);
205 err = vnet_netlink_msg_send (&m, NULL);
207 err = clib_error_return (0, "set link addr %U", format_clib_error, err);
212 vnet_netlink_set_link_state (int ifindex, int up)
214 vnet_netlink_msg_t m;
215 struct ifinfomsg ifmsg = { 0 };
216 clib_error_t *err = 0;
218 ifmsg.ifi_flags = ((up) ? IFF_UP : 0);
219 ifmsg.ifi_change = IFF_UP;
220 ifmsg.ifi_index = ifindex;
222 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
223 &ifmsg, sizeof (struct ifinfomsg));
224 err = vnet_netlink_msg_send (&m, NULL);
226 err = clib_error_return (0, "set link state %U", format_clib_error, err);
231 vnet_netlink_get_link_mtu (int ifindex, u32 *mtu)
233 vnet_netlink_msg_t m, *msg;
234 struct ifinfomsg ifmsg = { 0 };
236 clib_error_t *err = 0;
237 vnet_netlink_msg_t *replies = NULL;
238 int len = 0, offset = 0;
241 ifmsg.ifi_index = ifindex;
243 vnet_netlink_msg_init (&m, RTM_GETLINK, NLM_F_REQUEST, &ifmsg,
244 sizeof (struct ifinfomsg));
245 // vnet_netlink_msg_add_rtattr (&m, IFLA_MTU, &mtu, sizeof (int));
246 err = vnet_netlink_msg_send (&m, &replies);
249 err = clib_error_return (0, "get link mtu %U", format_clib_error, err);
253 if (vec_len (replies) != 1)
255 err = clib_error_return (0, "got %d != 1 netlink reply msg",
260 struct nlmsghdr *nh = (struct nlmsghdr *) replies[0].data;
261 if (nh->nlmsg_type != RTM_NEWLINK)
263 err = clib_error_return (
264 0, "netlink reply has wrong type: %d != RTM_NEWLINK", nh->nlmsg_type);
268 offset = NLMSG_HDRLEN + NLMSG_ALIGN (sizeof (struct ifinfomsg));
269 attr = (struct nlattr *) ((u8 *) nh + offset);
270 len = nh->nlmsg_len - offset;
274 if ((attr->nla_type & NLA_TYPE_MASK) == IFLA_MTU)
276 msg_mtu = *(u32 *) ((u8 *) attr + NLA_HDRLEN);
277 if (attr->nla_type & NLA_F_NET_BYTEORDER)
278 *mtu = clib_net_to_host_u32 (msg_mtu);
283 offset = NLA_ALIGN (attr->nla_len);
285 attr = (struct nlattr *) ((u8 *) attr + offset);
287 while (len > sizeof (struct nlattr));
290 err = clib_error_return (0, "mtu not found in netlink message");
293 vec_foreach (msg, replies)
295 vec_free (msg->data);
303 vnet_netlink_set_link_mtu (int ifindex, int mtu)
305 vnet_netlink_msg_t m;
306 struct ifinfomsg ifmsg = { 0 };
307 clib_error_t *err = 0;
309 ifmsg.ifi_index = ifindex;
311 vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
312 &ifmsg, sizeof (struct ifinfomsg));
313 vnet_netlink_msg_add_rtattr (&m, IFLA_MTU, &mtu, sizeof (int));
314 err = vnet_netlink_msg_send (&m, NULL);
316 err = clib_error_return (0, "set link mtu %U", format_clib_error, err);
321 vnet_netlink_add_ip4_addr (int ifindex, void *addr, int pfx_len)
323 vnet_netlink_msg_t m;
324 struct ifaddrmsg ifa = { 0 };
325 clib_error_t *err = 0;
327 ifa.ifa_family = AF_INET;
328 ifa.ifa_prefixlen = pfx_len;
329 ifa.ifa_index = ifindex;
331 vnet_netlink_msg_init (&m, RTM_NEWADDR,
332 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
333 &ifa, sizeof (struct ifaddrmsg));
335 vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 4);
336 vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 4);
337 err = vnet_netlink_msg_send (&m, NULL);
339 err = clib_error_return (0, "add ip4 addr %U", format_clib_error, err);
344 vnet_netlink_add_ip6_addr (int ifindex, void *addr, int pfx_len)
346 vnet_netlink_msg_t m;
347 struct ifaddrmsg ifa = { 0 };
348 clib_error_t *err = 0;
350 ifa.ifa_family = AF_INET6;
351 ifa.ifa_prefixlen = pfx_len;
352 ifa.ifa_index = ifindex;
354 vnet_netlink_msg_init (&m, RTM_NEWADDR,
355 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
356 &ifa, sizeof (struct ifaddrmsg));
358 vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 16);
359 vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 16);
360 err = vnet_netlink_msg_send (&m, NULL);
362 err = clib_error_return (0, "add ip6 addr %U", format_clib_error, err);
367 vnet_netlink_add_ip4_route (void *dst, u8 dst_len, void *gw)
369 vnet_netlink_msg_t m;
370 struct rtmsg rtm = { 0 };
372 clib_error_t *err = 0;
374 rtm.rtm_family = AF_INET;
375 rtm.rtm_table = RT_TABLE_MAIN;
376 rtm.rtm_type = RTN_UNICAST;
377 rtm.rtm_dst_len = dst_len;
379 vnet_netlink_msg_init (&m, RTM_NEWROUTE,
380 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
381 &rtm, sizeof (struct rtmsg));
383 vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 4);
384 vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 4);
385 err = vnet_netlink_msg_send (&m, NULL);
387 err = clib_error_return (0, "add ip4 route %U", format_clib_error, err);
392 vnet_netlink_add_ip6_route (void *dst, u8 dst_len, void *gw)
394 vnet_netlink_msg_t m;
395 struct rtmsg rtm = { 0 };
397 clib_error_t *err = 0;
399 rtm.rtm_family = AF_INET6;
400 rtm.rtm_table = RT_TABLE_MAIN;
401 rtm.rtm_type = RTN_UNICAST;
402 rtm.rtm_dst_len = dst_len;
404 vnet_netlink_msg_init (&m, RTM_NEWROUTE,
405 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,
406 &rtm, sizeof (struct rtmsg));
408 vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 16);
409 vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 16);
410 err = vnet_netlink_msg_send (&m, NULL);
412 err = clib_error_return (0, "add ip6 route %U", format_clib_error, err);
417 vnet_netlink_del_ip4_addr (int ifindex, void *addr, int pfx_len)
419 vnet_netlink_msg_t m;
420 struct ifaddrmsg ifa = { 0 };
421 clib_error_t *err = 0;
423 ifa.ifa_family = AF_INET;
424 ifa.ifa_prefixlen = pfx_len;
425 ifa.ifa_index = ifindex;
427 vnet_netlink_msg_init (&m, RTM_DELADDR, NLM_F_REQUEST, &ifa,
428 sizeof (struct ifaddrmsg));
430 vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 4);
431 vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 4);
432 err = vnet_netlink_msg_send (&m, NULL);
434 err = clib_error_return (0, "del ip4 addr %U", format_clib_error, err);
439 vnet_netlink_del_ip6_addr (int ifindex, void *addr, int pfx_len)
441 vnet_netlink_msg_t m;
442 struct ifaddrmsg ifa = { 0 };
443 clib_error_t *err = 0;
445 ifa.ifa_family = AF_INET6;
446 ifa.ifa_prefixlen = pfx_len;
447 ifa.ifa_index = ifindex;
449 vnet_netlink_msg_init (&m, RTM_DELADDR, NLM_F_REQUEST, &ifa,
450 sizeof (struct ifaddrmsg));
452 vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 16);
453 vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 16);
454 err = vnet_netlink_msg_send (&m, NULL);
456 err = clib_error_return (0, "del ip6 addr %U", format_clib_error, err);
461 * fd.io coding-style-patch-verification: ON
464 * eval: (c-set-style "gnu")