libnl  3.2.27
macvlan.c
1 /*
2  * lib/route/link/macvlan.c MACVLAN Link Info
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2013 Michael Braun <michael-dev@fami-braun.de>
10  */
11 
12 /**
13  * @ingroup link
14  * @defgroup macvlan MACVLAN
15  * MAC-based Virtual LAN link module
16  *
17  * @details
18  * \b Link Type Name: "macvlan"
19  *
20  * @route_doc{link_macvlan, MACVLAN Documentation}
21  *
22  * @{
23  */
24 
25 #include <netlink-private/netlink.h>
26 #include <netlink/netlink.h>
27 #include <netlink/attr.h>
28 #include <netlink/utils.h>
29 #include <netlink/object.h>
30 #include <netlink/route/rtnl.h>
31 #include <netlink-private/route/link/api.h>
32 #include <netlink/route/link/macvlan.h>
33 
34 #include <linux/if_link.h>
35 
36 /** @cond SKIP */
37 #define MACVLAN_HAS_MODE (1<<0)
38 #define MACVLAN_HAS_FLAGS (1<<1)
39 
40 struct macvlan_info
41 {
42  uint32_t mvi_mode;
43  uint16_t mvi_flags; // there currently is only one flag and kernel has no flags_mask yet
44  uint32_t mvi_mask;
45 };
46 
47 /** @endcond */
48 
49 static struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX+1] = {
50  [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
51  [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
52 };
53 
54 static int macvlan_alloc(struct rtnl_link *link)
55 {
56  struct macvlan_info *mvi;
57 
58  if (link->l_info)
59  memset(link->l_info, 0, sizeof(*mvi));
60  else {
61  if ((mvi = calloc(1, sizeof(*mvi))) == NULL)
62  return -NLE_NOMEM;
63 
64  link->l_info = mvi;
65  }
66 
67  return 0;
68 }
69 
70 static int macvlan_parse(struct rtnl_link *link, struct nlattr *data,
71  struct nlattr *xstats)
72 {
73  struct nlattr *tb[IFLA_MACVLAN_MAX+1];
74  struct macvlan_info *mvi;
75  int err;
76 
77  NL_DBG(3, "Parsing MACVLAN link info\n");
78 
79  if ((err = nla_parse_nested(tb, IFLA_MACVLAN_MAX, data, macvlan_policy)) < 0)
80  goto errout;
81 
82  if ((err = macvlan_alloc(link)) < 0)
83  goto errout;
84 
85  mvi = link->l_info;
86 
87  if (tb[IFLA_MACVLAN_MODE]) {
88  mvi->mvi_mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]);
89  mvi->mvi_mask |= MACVLAN_HAS_MODE;
90  }
91 
92  if (tb[IFLA_MACVLAN_FLAGS]) {
93  mvi->mvi_mode = nla_get_u16(tb[IFLA_MACVLAN_FLAGS]);
94  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
95  }
96 
97  err = 0;
98 errout:
99  return err;
100 }
101 
102 static void macvlan_free(struct rtnl_link *link)
103 {
104  free(link->l_info);
105  link->l_info = NULL;
106 }
107 
108 static void macvlan_dump(struct rtnl_link *link, struct nl_dump_params *p)
109 {
110  char buf[64];
111  struct macvlan_info *mvi = link->l_info;
112 
113  if (mvi->mvi_mask & MACVLAN_HAS_MODE) {
114  rtnl_link_macvlan_mode2str(mvi->mvi_mode, buf, sizeof(buf));
115  nl_dump(p, "macvlan-mode %s", buf);
116  }
117 
118  if (mvi->mvi_mask & MACVLAN_HAS_FLAGS) {
119  rtnl_link_macvlan_flags2str(mvi->mvi_flags, buf, sizeof(buf));
120  nl_dump(p, "macvlan-flags %s", buf);
121  }
122 }
123 
124 static int macvlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
125 {
126  struct macvlan_info *vdst, *vsrc = src->l_info;
127  int err;
128 
129  dst->l_info = NULL;
130  if ((err = rtnl_link_set_type(dst, "macvlan")) < 0)
131  return err;
132  vdst = dst->l_info;
133 
134  if (!vdst || !vsrc)
135  return -NLE_NOMEM;
136 
137  memcpy(vdst, vsrc, sizeof(struct macvlan_info));
138 
139  return 0;
140 }
141 
142 static int macvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
143 {
144  struct macvlan_info *mvi = link->l_info;
145  struct nlattr *data;
146 
147  if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
148  return -NLE_MSGSIZE;
149 
150  if (mvi->mvi_mask & MACVLAN_HAS_MODE)
151  NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, mvi->mvi_mode);
152 
153  if (mvi->mvi_mask & MACVLAN_HAS_FLAGS)
154  NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, mvi->mvi_flags);
155 
156  nla_nest_end(msg, data);
157 
158 nla_put_failure:
159 
160  return 0;
161 }
162 
163 static struct rtnl_link_info_ops macvlan_info_ops = {
164  .io_name = "macvlan",
165  .io_alloc = macvlan_alloc,
166  .io_parse = macvlan_parse,
167  .io_dump = {
168  [NL_DUMP_LINE] = macvlan_dump,
169  [NL_DUMP_DETAILS] = macvlan_dump,
170  },
171  .io_clone = macvlan_clone,
172  .io_put_attrs = macvlan_put_attrs,
173  .io_free = macvlan_free,
174 };
175 
176 /** @cond SKIP */
177 #define IS_MACVLAN_LINK_ASSERT(link) \
178  if ((link)->l_info_ops != &macvlan_info_ops) { \
179  APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \
180  return -NLE_OPNOTSUPP; \
181  }
182 /** @endcond */
183 
184 /**
185  * @name MACVLAN Object
186  * @{
187  */
188 
189 /**
190  * Allocate link object of type MACVLAN
191  *
192  * @return Allocated link object or NULL.
193  */
195 {
196  struct rtnl_link *link;
197  int err;
198 
199  if (!(link = rtnl_link_alloc()))
200  return NULL;
201 
202  if ((err = rtnl_link_set_type(link, "macvlan")) < 0) {
203  rtnl_link_put(link);
204  return NULL;
205  }
206 
207  return link;
208 }
209 
210 /**
211  * Check if link is a MACVLAN link
212  * @arg link Link object
213  *
214  * @return True if link is a MACVLAN link, otherwise false is returned.
215  */
217 {
218  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvlan");
219 }
220 
221 /**
222  * Set MACVLAN MODE
223  * @arg link Link object
224  * @arg mode MACVLAN mode
225  *
226  * @return 0 on success or a negative error code
227  */
228 int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
229 {
230  struct macvlan_info *mvi = link->l_info;
231 
232  IS_MACVLAN_LINK_ASSERT(link);
233 
234  mvi->mvi_mode = mode;
235  mvi->mvi_mask |= MACVLAN_HAS_MODE;
236 
237  return 0;
238 }
239 
240 /**
241  * Get MACVLAN Mode
242  * @arg link Link object
243  *
244  * @return MACVLAN mode, 0 if not set or a negative error code.
245  */
246 uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
247 {
248  struct macvlan_info *mvi = link->l_info;
249 
250  IS_MACVLAN_LINK_ASSERT(link);
251 
252  if (mvi->mvi_mask & MACVLAN_HAS_MODE)
253  return mvi->mvi_mode;
254  else
255  return 0;
256 }
257 
258 /**
259  * Set MACVLAN flags
260  * @arg link Link object
261  * @arg flags MACVLAN flags
262  *
263  * @return 0 on success or a negative error code.
264  */
265 int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
266 {
267  struct macvlan_info *mvi = link->l_info;
268 
269  IS_MACVLAN_LINK_ASSERT(link);
270 
271  mvi->mvi_flags |= flags;
272  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
273 
274  return 0;
275 }
276 
277 /**
278  * Unset MACVLAN flags
279  * @arg link Link object
280  * @arg flags MACVLAN flags
281  *
282  * Note: kernel currently only has a single flag and lacks flags_mask to
283  * indicate which flags shall be changed (it always all).
284  *
285  * @return 0 on success or a negative error code.
286  */
287 int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
288 {
289  struct macvlan_info *mvi = link->l_info;
290 
291  IS_MACVLAN_LINK_ASSERT(link);
292 
293  mvi->mvi_flags &= ~flags;
294  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
295 
296  return 0;
297 }
298 
299 /**
300  * Get MACVLAN flags
301  * @arg link Link object
302  *
303  * @return MACVLAN flags, 0 if none set, or a negative error code.
304  */
306 {
307  struct macvlan_info *mvi = link->l_info;
308 
309  IS_MACVLAN_LINK_ASSERT(link);
310 
311  return mvi->mvi_flags;
312 }
313 
314 /** @} */
315 
316 static const struct trans_tbl macvlan_flags[] = {
317  __ADD(MACVLAN_FLAG_NOPROMISC, nopromisc),
318 };
319 
320 static const struct trans_tbl macvlan_modes[] = {
321  __ADD(MACVLAN_MODE_PRIVATE, private),
322  __ADD(MACVLAN_MODE_VEPA, vepa),
323  __ADD(MACVLAN_MODE_BRIDGE, bridge),
324  __ADD(MACVLAN_MODE_PASSTHRU, passthru),
325 };
326 
327 /**
328  * @name Flag Translation
329  * @{
330  */
331 
332 char *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len)
333 {
334  return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
335 }
336 
337 int rtnl_link_macvlan_str2flags(const char *name)
338 {
339  return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
340 }
341 
342 /** @} */
343 
344 /**
345  * @name Mode Translation
346  * @{
347  */
348 
349 char *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len)
350 {
351  return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
352 }
353 
354 int rtnl_link_macvlan_str2mode(const char *name)
355 {
356  return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
357 }
358 
359 /** @} */
360 
361 static void __init macvlan_init(void)
362 {
363  rtnl_link_register_info(&macvlan_info_ops);
364 }
365 
366 static void __exit macvlan_exit(void)
367 {
368  rtnl_link_unregister_info(&macvlan_info_ops);
369 }
370 
371 /** @} */
Dump object briefly on one line.
Definition: types.h:22
int rtnl_link_is_macvlan(struct rtnl_link *link)
Check if link is a MACVLAN link.
Definition: macvlan.c:216
int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVLAN flags.
Definition: macvlan.c:287
uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link)
Get MACVLAN flags.
Definition: macvlan.c:305
Attribute validation policy.
Definition: attr.h:67
uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
Get MACVLAN Mode.
Definition: macvlan.c:246
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
Dump all attributes but no statistics.
Definition: types.h:23
int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVLAN flags.
Definition: macvlan.c:265
int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVLAN MODE.
Definition: macvlan.c:228
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:917
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:991
16 bit integer
Definition: attr.h:40
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:233
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:69
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
32 bit integer
Definition: attr.h:41
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:215
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:914
struct rtnl_link * rtnl_link_macvlan_alloc(void)
Allocate link object of type MACVLAN.
Definition: macvlan.c:194
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895