FD.io VPP  v19.04.4-rc0-5-ge88582fac
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 
120  ifmsg.ifi_index = ifindex;
121  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
122  &ifmsg, sizeof (struct ifinfomsg));
123 
124  vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
125  strlen (new_ifname) + 1);
126 
127  return vnet_netlink_msg_send (&m);
128 }
129 
130 clib_error_t *
131 vnet_netlink_set_link_netns (int ifindex, int netns_fd, char *new_ifname)
132 {
134  struct ifinfomsg ifmsg = { 0 };
135 
136  ifmsg.ifi_index = ifindex;
137  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
138  &ifmsg, sizeof (struct ifinfomsg));
139 
140  vnet_netlink_msg_add_rtattr (&m, IFLA_NET_NS_FD, &netns_fd, sizeof (int));
141  if (new_ifname)
142  vnet_netlink_msg_add_rtattr (&m, IFLA_IFNAME, new_ifname,
143  strlen (new_ifname) + 1);
144 
145  return vnet_netlink_msg_send (&m);
146 }
147 
148 clib_error_t *
149 vnet_netlink_set_link_master (int ifindex, char *master_ifname)
150 {
152  struct ifinfomsg ifmsg = { 0 };
153  int i;
154 
155  ifmsg.ifi_index = ifindex;
156 
157  if ((i = if_nametoindex (master_ifname)) == 0)
158  clib_error_return_unix (0, "unknown master interface '%s'",
159  master_ifname);
160 
161  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
162  &ifmsg, sizeof (struct ifinfomsg));
163  vnet_netlink_msg_add_rtattr (&m, IFLA_MASTER, &i, sizeof (int));
164  return vnet_netlink_msg_send (&m);
165 }
166 
167 clib_error_t *
169 {
171  struct ifinfomsg ifmsg = { 0 };
172 
173  ifmsg.ifi_index = ifindex;
174 
175  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
176  &ifmsg, sizeof (struct ifinfomsg));
177  vnet_netlink_msg_add_rtattr (&m, IFLA_ADDRESS, mac, 6);
178  return vnet_netlink_msg_send (&m);
179 }
180 
181 clib_error_t *
182 vnet_netlink_set_link_state (int ifindex, int up)
183 {
185  struct ifinfomsg ifmsg = { 0 };
186 
187  ifmsg.ifi_flags = IFF_UP;
188  ifmsg.ifi_change = IFF_UP;
189  ifmsg.ifi_index = ifindex;
190 
191  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
192  &ifmsg, sizeof (struct ifinfomsg));
193  return vnet_netlink_msg_send (&m);
194 }
195 
196 clib_error_t *
197 vnet_netlink_set_link_mtu (int ifindex, int mtu)
198 {
200  struct ifinfomsg ifmsg = { 0 };
201 
202  ifmsg.ifi_index = ifindex;
203 
204  vnet_netlink_msg_init (&m, RTM_SETLINK, NLM_F_REQUEST,
205  &ifmsg, sizeof (struct ifinfomsg));
206  vnet_netlink_msg_add_rtattr (&m, IFLA_MTU, &mtu, sizeof (int));
207  return vnet_netlink_msg_send (&m);
208 }
209 
210 clib_error_t *
211 vnet_netlink_add_ip4_addr (int ifindex, void *addr, int pfx_len)
212 {
214  struct ifaddrmsg ifa = { 0 };
215 
216  ifa.ifa_family = AF_INET;
217  ifa.ifa_prefixlen = pfx_len;
218  ifa.ifa_index = ifindex;
219 
220  vnet_netlink_msg_init (&m, RTM_NEWADDR,
221  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL,
222  &ifa, sizeof (struct ifaddrmsg));
223 
224  vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 4);
225  vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 4);
226  return vnet_netlink_msg_send (&m);
227 }
228 
229 clib_error_t *
230 vnet_netlink_add_ip6_addr (int ifindex, void *addr, int pfx_len)
231 {
233  struct ifaddrmsg ifa = { 0 };
234 
235  ifa.ifa_family = AF_INET6;
236  ifa.ifa_prefixlen = pfx_len;
237  ifa.ifa_index = ifindex;
238 
239  vnet_netlink_msg_init (&m, RTM_NEWADDR,
240  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL,
241  &ifa, sizeof (struct ifaddrmsg));
242 
243  vnet_netlink_msg_add_rtattr (&m, IFA_LOCAL, addr, 16);
244  vnet_netlink_msg_add_rtattr (&m, IFA_ADDRESS, addr, 16);
245  return vnet_netlink_msg_send (&m);
246 }
247 
248 clib_error_t *
249 vnet_netlink_add_ip4_route (void *dst, u8 dst_len, void *gw)
250 {
252  struct rtmsg rtm = { 0 };
253  u8 dflt[4] = { 0 };
254 
255  rtm.rtm_family = AF_INET;
256  rtm.rtm_table = RT_TABLE_MAIN;
257  rtm.rtm_type = RTN_UNICAST;
258  rtm.rtm_dst_len = dst_len;
259 
260  vnet_netlink_msg_init (&m, RTM_NEWROUTE,
261  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL,
262  &rtm, sizeof (struct rtmsg));
263 
264  vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 4);
265  vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 4);
266  return vnet_netlink_msg_send (&m);
267 }
268 
269 clib_error_t *
270 vnet_netlink_add_ip6_route (void *dst, u8 dst_len, void *gw)
271 {
273  struct rtmsg rtm = { 0 };
274  u8 dflt[16] = { 0 };
275 
276  rtm.rtm_family = AF_INET6;
277  rtm.rtm_table = RT_TABLE_MAIN;
278  rtm.rtm_type = RTN_UNICAST;
279  rtm.rtm_dst_len = dst_len;
280 
281  vnet_netlink_msg_init (&m, RTM_NEWROUTE,
282  NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL,
283  &rtm, sizeof (struct rtmsg));
284 
285  vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 16);
286  vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 16);
287  return vnet_netlink_msg_send (&m);
288 }
289 
290 /*
291  * fd.io coding-style-patch-verification: ON
292  *
293  * Local Variables:
294  * eval: (c-set-style "gnu")
295  * End:
296  */
u32 flags
Definition: vhost_user.h:115
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:560
int i
vl_api_ip4_address_t dst
Definition: ipsec_gre.api:39
vhost_vring_addr_t addr
Definition: vhost_user.h:121
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
unsigned short u16
Definition: types.h:57
#define clib_error_return_unix(e, args...)
Definition: error.h:102
u8 len
Definition: ip_types.api:49
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#define ASSERT(truth)
unsigned int if_nametoindex(const char *ifname)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vl_api_mac_address_t mac
Definition: gbp.api:120