libnl: /data/src/libnl3/lib/route/link/veth.c Source File

libnl 3.10.0

veth.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup veth VETH
9 * Virtual Ethernet
10 *
11 * @details
12 * \b Link Type Name: "veth"
13 *
14 * @route_doc{link_veth, VETH Documentation}
15 *
16 * @{
17 */
18
19#include "nl-default.h"
20
21#include <linux/if_link.h>
22#include <linux/veth.h>
23
24#include <netlink/netlink.h>
25#include <netlink/attr.h>
26#include <netlink/utils.h>
27#include <netlink/object.h>
28#include <netlink/route/rtnl.h>
29#include <netlink/route/link/veth.h>
30
31#include "nl-route.h"
32#include "link-api.h"
33
34static struct nla_policy veth_policy[VETH_INFO_MAX+1] = {
35 [VETH_INFO_PEER] = { .minlen = sizeof(struct ifinfomsg) },
36};
37
38static int veth_parse(struct rtnl_link *link, struct nlattr *data,
39 struct nlattr *xstats)
40{
41 struct nlattr *tb[VETH_INFO_MAX+1];
42 struct nlattr *peer_tb[IFLA_MAX + 1];
43 struct rtnl_link *peer = link->l_info;
44 int err;
45
46 NL_DBG(3, "Parsing veth link info\n");
47
48 if ((err = nla_parse_nested(tb, VETH_INFO_MAX, data, veth_policy)) < 0)
49 goto errout;
50
51 if (tb[VETH_INFO_PEER]) {
52 struct nlattr *nla_peer;
53 struct ifinfomsg *ifi;
54
55 nla_peer = tb[VETH_INFO_PEER];
56 ifi = nla_data(nla_peer);
57
58 peer->l_family = ifi->ifi_family;
59 peer->l_arptype = ifi->ifi_type;
60 peer->l_index = ifi->ifi_index;
61 peer->l_flags = ifi->ifi_flags;
62 peer->l_change = ifi->ifi_change;
63 err = nla_parse(peer_tb, IFLA_MAX, (struct nlattr *)
64 ((char *) nla_data(nla_peer) + sizeof(struct ifinfomsg)),
65 nla_len(nla_peer) - sizeof(struct ifinfomsg),
66 rtln_link_policy);
67 if (err < 0)
68 goto errout;
69
70 err = rtnl_link_info_parse(peer, peer_tb);
71 if (err < 0)
72 goto errout;
73 }
74
75 err = 0;
76
77errout:
78 return err;
79}
80
81static void veth_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
82{
83}
84
85static void veth_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
86{
87 struct rtnl_link *peer = link->l_info;
88 char *name;
89 name = rtnl_link_get_name(peer);
90 nl_dump(p, " peer ");
91 if (name)
92 nl_dump_line(p, "%s\n", name);
93 else
94 nl_dump_line(p, "%u\n", peer->l_index);
95}
96
97static int veth_clone(struct rtnl_link *dst, struct rtnl_link *src)
98{
99 struct rtnl_link *dst_peer = NULL, *src_peer = src->l_info;
100
101 /* we are calling nl_object_clone() recursively, this should
102 * happen only once */
103 if (src_peer) {
104 src_peer->l_info = NULL;
105 dst_peer = (struct rtnl_link *)nl_object_clone(OBJ_CAST(src_peer));
106 if (!dst_peer)
107 return -NLE_NOMEM;
108 src_peer->l_info = src;
109 dst_peer->l_info = dst;
110 }
111 dst->l_info = dst_peer;
112 return 0;
113}
114
115static int veth_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
116{
117 struct rtnl_link *peer = link->l_info;
118 struct ifinfomsg ifi;
119 struct nlattr *data, *info_peer;
120
121 memset(&ifi, 0, sizeof ifi);
122 ifi.ifi_family = peer->l_family;
123 ifi.ifi_type = peer->l_arptype;
124 ifi.ifi_index = peer->l_index;
125 ifi.ifi_flags = peer->l_flags;
126 ifi.ifi_change = peer->l_change;
127
128 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
129 return -NLE_MSGSIZE;
130 if (!(info_peer = nla_nest_start(msg, VETH_INFO_PEER)))
131 return -NLE_MSGSIZE;
132 if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
133 return -NLE_MSGSIZE;
134 rtnl_link_fill_info(msg, peer);
135 nla_nest_end(msg, info_peer);
136 nla_nest_end(msg, data);
137
138 return 0;
139}
140
141static int veth_alloc(struct rtnl_link *link)
142{
143 struct rtnl_link *peer;
144 int err;
145
146 /* return early if we are in recursion */
147 if (link->l_info)
148 return 0;
149
150 if (!(peer = rtnl_link_alloc()))
151 return -NLE_NOMEM;
152
153 /* We don't need to hold a reference here, as link and
154 * its peer should always be freed together.
155 */
156 peer->l_info = link;
157 if ((err = rtnl_link_set_type(peer, "veth")) < 0) {
158 rtnl_link_put(peer);
159 return err;
160 }
161
162 link->l_info = peer;
163 return 0;
164}
165
166static void veth_free(struct rtnl_link *link)
167{
168 struct rtnl_link *peer = link->l_info;
169 if (peer) {
170 link->l_info = NULL;
171 /* avoid calling this recursively */
172 peer->l_info = NULL;
173 rtnl_link_put(peer);
174 }
175 /* the caller should finally free link */
176}
177
178static struct rtnl_link_info_ops veth_info_ops = {
179 .io_name = "veth",
180 .io_parse = veth_parse,
181 .io_dump = {
182 [NL_DUMP_LINE] = veth_dump_line,
183 [NL_DUMP_DETAILS] = veth_dump_details,
184 },
185 .io_alloc = veth_alloc,
186 .io_clone = veth_clone,
187 .io_put_attrs = veth_put_attrs,
188 .io_free = veth_free,
189};
190
191/** @cond SKIP */
192
193#define IS_VETH_LINK_ASSERT(link) \
194 if ((link)->l_info_ops != &veth_info_ops) { \
195 APPBUG("Link is not a veth link. set type \"veth\" first."); \
196 return NULL; \
197 }
198/** @endcond */
199
200/**
201 * @name VETH Object
202 * @{
203 */
204
205/**
206 * Allocate link object of type veth
207 *
208 * @return Allocated link object or NULL.
209 */
210 struct rtnl_link *rtnl_link_veth_alloc(void)
211{
212 struct rtnl_link *link;
213
214 if (!(link = rtnl_link_alloc()))
215 return NULL;
216 if (rtnl_link_set_type(link, "veth") < 0) {
217 rtnl_link_put(link);
218 return NULL;
219 }
220
221 return link;
222}
223
224/**
225 * Get the peer link of a veth link
226 *
227 * @return the peer link object.
228 */
229 struct rtnl_link *rtnl_link_veth_get_peer(struct rtnl_link *link)
230{
231 IS_VETH_LINK_ASSERT(link);
232 nl_object_get(OBJ_CAST(link->l_info));
233 return link->l_info;
234}
235
236/**
237 * Release a veth link and its peer
238 *
239 */
240 void rtnl_link_veth_release(struct rtnl_link *link)
241{
242 veth_free(link);
243 rtnl_link_put(link);
244}
245
246/**
247 * Check if link is a veth link
248 * @arg link Link object
249 *
250 * @return True if link is a veth link, otherwise false is returned.
251 */
252 int rtnl_link_is_veth(struct rtnl_link *link)
253{
254 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "veth");
255}
256
257/**
258 * Create a new kernel veth device
259 * @arg sock netlink socket
260 * @arg name name of the veth device or NULL
261 * @arg peer_name name of its peer or NULL
262 * @arg pid pid of the process in the new netns
263 *
264 * Creates a new veth device pair in the kernel and move the peer
265 * to the network namespace where the process is. If no name is
266 * provided, the kernel will automatically pick a name of the
267 * form "veth%d" (e.g. veth0, veth1, etc.)
268 *
269 * @return 0 on success or a negative error code
270 */
271 int rtnl_link_veth_add(struct nl_sock *sock, const char *name,
272 const char *peer_name, pid_t pid)
273{
274 struct rtnl_link *link, *peer;
275 int err = -NLE_NOMEM;
276
277 if (!(link = rtnl_link_veth_alloc()))
278 return -NLE_NOMEM;
279 peer = link->l_info;
280
281 if (name)
282 rtnl_link_set_name(link, name);
283 if (peer_name)
284 rtnl_link_set_name(peer, peer_name);
285
286 rtnl_link_set_ns_pid(peer, pid);
287 err = rtnl_link_add(sock, link, NLM_F_CREATE | NLM_F_EXCL);
288
289 rtnl_link_put(link);
290 return err;
291}
292
293/** @} */
294
295static void _nl_init veth_init(void)
296{
297 rtnl_link_register_info(&veth_info_ops);
298}
299
300static void _nl_exit veth_exit(void)
301{
302 rtnl_link_unregister_info(&veth_info_ops);
303}
304
305/** @} */
nla_parse
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy)
Create attribute index based on a stream of attributes.
Definition attr.c:243
nla_data
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
nla_nest_start
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:908
nla_parse_nested
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1035
nla_len
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
nla_nest_end
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:971
rtnl_link_register_info
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
Definition api.c:127
rtnl_link_unregister_info
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
Definition api.c:162
rtnl_link_add
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
Definition link.c:1694
rtnl_link_alloc
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
Definition link.c:1920
rtnl_link_set_name
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
Definition link.c:1948
rtnl_link_get_name
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
Definition link.c:1962
rtnl_link_put
void rtnl_link_put(struct rtnl_link *link)
Release a link object reference.
Definition link.c:1929
rtnl_link_set_type
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
Definition link.c:2558
nlmsg_append
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition msg.c:456
nl_object_clone
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
Definition object.c:111
nl_object_get
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition object.c:210
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
NL_DUMP_LINE
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
rtnl_link_veth_get_peer
struct rtnl_link * rtnl_link_veth_get_peer(struct rtnl_link *link)
Get the peer link of a veth link.
Definition veth.c:229
rtnl_link_veth_add
int rtnl_link_veth_add(struct nl_sock *sock, const char *name, const char *peer_name, pid_t pid)
Create a new kernel veth device.
Definition veth.c:271
rtnl_link_veth_release
void rtnl_link_veth_release(struct rtnl_link *link)
Release a veth link and its peer.
Definition veth.c:240
rtnl_link_is_veth
int rtnl_link_is_veth(struct rtnl_link *link)
Check if link is a veth link.
Definition veth.c:252
rtnl_link_veth_alloc
struct rtnl_link * rtnl_link_veth_alloc(void)
Allocate link object of type veth.
Definition veth.c:210
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:63
nla_policy::minlen
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68
nla_policy::type
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65
rtnl_link_info_ops
Available operations to modules implementing a link info type.
Definition link-api.h:20
rtnl_link_info_ops::io_name
char * io_name
Name of link info type, must match name on kernel side.
Definition link-api.h:22
rtnl_link
Link object.
Definition nl-route.h:29