1054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/*
2054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * lib/route/link/macvlan.c	MACVLAN Link Info
3054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
4054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *	This library is free software; you can redistribute it and/or
5054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *	modify it under the terms of the GNU Lesser General Public
6054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *	License as published by the Free Software Foundation version 2.1
7054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *	of the License.
8054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2013 Michael Braun <michael-dev@fami-braun.de>
10054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
11054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
12054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
13054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @ingroup link
14054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @defgroup macvlan MACVLAN
15054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * MAC-based Virtual LAN link module
16054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
17054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @details
18054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * \b Link Type Name: "macvlan"
19054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
20054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @route_doc{link_macvlan, MACVLAN Documentation}
21054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
22054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @{
23054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
24054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
25054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/netlink.h>
26054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/netlink.h>
27054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/attr.h>
28054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/utils.h>
29054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/object.h>
30054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/route/rtnl.h>
31054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/route/link/api.h>
32054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink/route/link/macvlan.h>
33054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
34054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <linux/if_link.h>
35054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
36054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @cond SKIP */
37054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define MACVLAN_HAS_MODE	(1<<0)
38054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define MACVLAN_HAS_FLAGS	(1<<1)
39054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
40054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstruct macvlan_info
41054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
42054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	uint32_t		mvi_mode;
43054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	uint16_t		mvi_flags; // there currently is only one flag and kernel has no flags_mask yet
44054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	uint32_t		mvi_mask;
45054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart};
46054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
47054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @endcond */
48054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
49054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX+1] = {
50054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[IFLA_MACVLAN_MODE]	= { .type = NLA_U32 },
51054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[IFLA_MACVLAN_FLAGS]	= { .type = NLA_U16 },
52054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart};
53054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
54054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic int macvlan_alloc(struct rtnl_link *link)
55054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
56054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi;
57054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
58054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((mvi = calloc(1, sizeof(*mvi))) == NULL)
59054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_NOMEM;
60054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
61054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	link->l_info = mvi;
62054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
63054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
64054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
65054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
66054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic int macvlan_parse(struct rtnl_link *link, struct nlattr *data,
67054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart                         struct nlattr *xstats)
68054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
69054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct nlattr *tb[IFLA_MACVLAN_MAX+1];
70054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi;
71054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	int err;
72054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
73054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	NL_DBG(3, "Parsing MACVLAN link info");
74054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
75054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((err = nla_parse_nested(tb, IFLA_MACVLAN_MAX, data, macvlan_policy)) < 0)
76054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		goto errout;
77054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
78054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((err = macvlan_alloc(link)) < 0)
79054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		goto errout;
80054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
81054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi = link->l_info;
82054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
83054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[IFLA_MACVLAN_MODE]) {
84054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		mvi->mvi_mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]);
85054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		mvi->mvi_mask |= MACVLAN_HAS_MODE;
86054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
87054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
88054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[IFLA_MACVLAN_FLAGS]) {
89054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		mvi->mvi_mode = nla_get_u16(tb[IFLA_MACVLAN_FLAGS]);
90054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
91054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
92054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
93054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	err = 0;
94054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewarterrout:
95054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return err;
96054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
97054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
98054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic void macvlan_free(struct rtnl_link *link)
99054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
100054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	free(link->l_info);
101054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	link->l_info = NULL;
102054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
103054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
104054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic void macvlan_dump(struct rtnl_link *link, struct nl_dump_params *p)
105054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
106054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	char buf[64];
107054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
108054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
109054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (mvi->mvi_mask & MACVLAN_HAS_MODE) {
110054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rtnl_link_macvlan_mode2str(mvi->mvi_mode, buf, sizeof(buf));
111054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "macvlan-mode %s", buf);
112054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
113054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
114054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (mvi->mvi_mask & MACVLAN_HAS_FLAGS) {
115054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rtnl_link_macvlan_flags2str(mvi->mvi_flags, buf, sizeof(buf));
116054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "macvlan-flags %s", buf);
117054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
118054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
119054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
120054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic int macvlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
121054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
122054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *vdst, *vsrc = src->l_info;
123054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	int err;
124054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
125054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	dst->l_info = NULL;
126054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((err = rtnl_link_set_type(dst, "macvlan")) < 0)
127054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return err;
128054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	vdst = dst->l_info;
129054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
130054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (!vdst || !vsrc)
131054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_NOMEM;
132054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
133054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	memcpy(vdst, vsrc, sizeof(struct macvlan_info));
134054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
135054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
136054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
137054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
138054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic int macvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
139054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
140054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
141054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct nlattr *data;
142054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
143054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
144054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_MSGSIZE;
145054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
146054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (mvi->mvi_mask & MACVLAN_HAS_MODE)
147054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, mvi->mvi_mode);
148054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
149054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (mvi->mvi_mask & MACVLAN_HAS_FLAGS)
150054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, mvi->mvi_flags);
151054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
152054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	nla_nest_end(msg, data);
153054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
154054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartnla_put_failure:
155054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
156054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
157054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
158054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
159054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic struct rtnl_link_info_ops macvlan_info_ops = {
160054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_name		= "macvlan",
161054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_alloc		= macvlan_alloc,
162054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_parse		= macvlan_parse,
163054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_dump = {
164054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	    [NL_DUMP_LINE]	= macvlan_dump,
165054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	    [NL_DUMP_DETAILS]	= macvlan_dump,
166054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	},
167054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_clone		= macvlan_clone,
168054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_put_attrs		= macvlan_put_attrs,
169054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.io_free		= macvlan_free,
170054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart};
171054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
172054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @cond SKIP */
173054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define IS_MACVLAN_LINK_ASSERT(link) \
174054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((link)->l_info_ops != &macvlan_info_ops) { \
175054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \
176054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_OPNOTSUPP; \
177054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
178054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @endcond */
179054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
180054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
181054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name MACVLAN Object
182054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @{
183054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
184054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
185054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
186054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Allocate link object of type MACVLAN
187054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
188054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return Allocated link object or NULL.
189054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
190054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstruct rtnl_link *rtnl_link_macvlan_alloc(void)
191054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
192054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct rtnl_link *link;
193054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	int err;
194054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
195054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (!(link = rtnl_link_alloc()))
196054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return NULL;
197054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
198054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if ((err = rtnl_link_set_type(link, "macvlan")) < 0) {
199054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rtnl_link_put(link);
200054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return NULL;
201054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
202054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
203054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return link;
204054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
205054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
206054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
207054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Check if link is a MACVLAN link
208054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
209054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
210054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return True if link is a MACVLAN link, otherwise false is returned.
211054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
212054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_is_macvlan(struct rtnl_link *link)
213054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
214054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvlan");
215054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
216054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
217054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
218054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Set MACVLAN MODE
219054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
220054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg mode		MACVLAN mode
221054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
222054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code
223054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
224054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
225054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
226054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
227054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
228054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	IS_MACVLAN_LINK_ASSERT(link);
229054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
230054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_mode = mode;
231054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_mask |= MACVLAN_HAS_MODE;
232054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
233054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
234054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
235054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
236054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
237054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Get MACVLAN Mode
238054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
239054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
240054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return MACVLAN mode, 0 if not set or a negative error code.
241054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
242054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
243054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
244054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
245054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
246054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	IS_MACVLAN_LINK_ASSERT(link);
247054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
248054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (mvi->mvi_mask & MACVLAN_HAS_MODE)
249054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return mvi->mvi_mode;
250054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	else
251054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return 0;
252054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
253054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
254054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
255054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Set MACVLAN flags
256054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
257054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg flags		MACVLAN flags
258054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
259054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code.
260054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
261054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
262054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
263054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
264054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
265054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	IS_MACVLAN_LINK_ASSERT(link);
266054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
267054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_flags |= flags;
268054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
269054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
270054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
271054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
272054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
273054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
274054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Unset MACVLAN flags
275054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
276054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg flags		MACVLAN flags
277054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
278054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Note: kernel currently only has a single flag and lacks flags_mask to
279054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * indicate which flags shall be changed (it always all).
280054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
281054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code.
282054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
283054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
284054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
285054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
286054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
287054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	IS_MACVLAN_LINK_ASSERT(link);
288054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
289054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_flags &= ~flags;
290054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
291054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
292054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
293054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
294054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
295054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
296054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Get MACVLAN flags
297054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg link		Link object
298054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
299054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return MACVLAN flags, 0 if none set, or a negative error code.
300054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
301054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link)
302054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
303054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct macvlan_info *mvi = link->l_info;
304054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
305054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	IS_MACVLAN_LINK_ASSERT(link);
306054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
307054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return mvi->mvi_flags;
308054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
309054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
310054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @} */
311054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
312054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic const struct trans_tbl macvlan_flags[] = {
313054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(MACVLAN_FLAG_NOPROMISC, nopromisc)
314054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart};
315054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
316054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic const struct trans_tbl macvlan_modes[] = {
317054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(MACVLAN_MODE_PRIVATE, private)
318054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(MACVLAN_MODE_VEPA, vepa)
319054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(MACVLAN_MODE_BRIDGE, bridge)
320054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(MACVLAN_MODE_PASSTHRU, passthru)
321054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart};
322054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
323054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
324054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Flag Translation
325054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @{
326054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
327054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
328054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartchar *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len)
329054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
330054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
331054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
332054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
333054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_macvlan_str2flags(const char *name)
334054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
335054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
336054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
337054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
338054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @} */
339054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
340054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/**
341054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @name Mode Translation
342054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @{
343054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart */
344054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
345054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartchar *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len)
346054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
347054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
348054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
349054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
350054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_link_macvlan_str2mode(const char *name)
351054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
352054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
353054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
354054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
355054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @} */
356054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
357054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic void __init macvlan_init(void)
358054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
359054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rtnl_link_register_info(&macvlan_info_ops);
360054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
361054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
362054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic void __exit macvlan_exit(void)
363054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
364054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rtnl_link_unregister_info(&macvlan_info_ops);
365054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
366054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
367054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart/** @} */
368