mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
network: add support for MACVLAN source mode
Add support for creating a MACVLAN interface in "source" mode by specifying Mode=source in the [MACVLAN] section of a .netdev file. A list of allowed MAC addresses for the corresponding MACVLAN can also be specified with the SourceMACAddress= option of the [MACVLAN] section. An example .netdev file: [NetDev] Name=macvlan0 Kind=macvlan MACAddress=02:DE:AD:BE:EF:00 [MACVLAN] Mode=source SourceMACAddress=02:AB:AB:AB:AB:01 02:CD:CD:CD:CD:01 SourceMACAddress=02:EF:EF:EF:EF:01 The same keys can also be specified in [MACVTAP] for MACVTAP kinds of interfaces, with the same semantics.
This commit is contained in:
parent
24e2494407
commit
0d0de133f0
@ -499,11 +499,22 @@
|
||||
<para>The MACVLAN mode to use. The supported options are
|
||||
<literal>private</literal>,
|
||||
<literal>vepa</literal>,
|
||||
<literal>bridge</literal>, and
|
||||
<literal>passthru</literal>.
|
||||
<literal>bridge</literal>,
|
||||
<literal>passthru</literal>, and
|
||||
<literal>source</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>SourceMACAddress=</varname></term>
|
||||
<listitem>
|
||||
<para>A whitespace-separated list of remote hardware addresses allowed on the MACVLAN. This
|
||||
option only has an affect in source mode. Use full colon-, hyphen- or dot-delimited
|
||||
hexadecimal. This option may appear more than once, in which case the lists are merged. If
|
||||
the empty string is assigned to this option, the list of hardware addresses defined prior
|
||||
to this is reset. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -93,9 +93,20 @@ static const NLType rtnl_link_info_data_ipvlan_types[] = {
|
||||
[IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_macvlan_macaddr_types[] = {
|
||||
[IFLA_MACVLAN_MACADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_macvlan_macaddr_type_system = {
|
||||
.count = ELEMENTSOF(rtnl_macvlan_macaddr_types),
|
||||
.types = rtnl_macvlan_macaddr_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_macvlan_types[] = {
|
||||
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_MACVLAN_MACADDR_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_MACADDR_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_macvlan_macaddr_type_system },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bridge_types[] = {
|
||||
|
@ -23,6 +23,29 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->mode == NETDEV_MACVLAN_MODE_SOURCE && !set_isempty(m->match_source_mac)) {
|
||||
Iterator i;
|
||||
const struct ether_addr *mac_addr;
|
||||
|
||||
r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MACADDR_MODE, MACVLAN_MACADDR_SET);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MACADDR_MODE attribute: %m");
|
||||
|
||||
r = sd_netlink_message_open_container(req, IFLA_MACVLAN_MACADDR_DATA);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not open IFLA_MACVLAN_MACADDR_DATA container: %m");
|
||||
|
||||
SET_FOREACH(mac_addr, m->match_source_mac, i) {
|
||||
r = sd_netlink_message_append_ether_addr(req, IFLA_MACVLAN_MACADDR, mac_addr);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MACADDR attribute: %m");
|
||||
}
|
||||
|
||||
r = sd_netlink_message_close_container(req);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not close IFLA_MACVLAN_MACADDR_DATA container: %m");
|
||||
}
|
||||
|
||||
if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) {
|
||||
r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode);
|
||||
if (r < 0)
|
||||
@ -32,6 +55,21 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void macvlan_done(NetDev *n) {
|
||||
MacVlan *m;
|
||||
|
||||
assert(n);
|
||||
|
||||
if (n->kind == NETDEV_KIND_MACVLAN)
|
||||
m = MACVLAN(n);
|
||||
else
|
||||
m = MACVTAP(n);
|
||||
|
||||
assert(m);
|
||||
|
||||
set_free_free(m->match_source_mac);
|
||||
}
|
||||
|
||||
static void macvlan_init(NetDev *n) {
|
||||
MacVlan *m;
|
||||
|
||||
@ -50,6 +88,7 @@ static void macvlan_init(NetDev *n) {
|
||||
const NetDevVTable macvtap_vtable = {
|
||||
.object_size = sizeof(MacVlan),
|
||||
.init = macvlan_init,
|
||||
.done = macvlan_done,
|
||||
.sections = NETDEV_COMMON_SECTIONS "MACVTAP\0",
|
||||
.fill_message_create = netdev_macvlan_fill_message_create,
|
||||
.create_type = NETDEV_CREATE_STACKED,
|
||||
@ -59,6 +98,7 @@ const NetDevVTable macvtap_vtable = {
|
||||
const NetDevVTable macvlan_vtable = {
|
||||
.object_size = sizeof(MacVlan),
|
||||
.init = macvlan_init,
|
||||
.done = macvlan_done,
|
||||
.sections = NETDEV_COMMON_SECTIONS "MACVLAN\0",
|
||||
.fill_message_create = netdev_macvlan_fill_message_create,
|
||||
.create_type = NETDEV_CREATE_STACKED,
|
||||
|
@ -5,11 +5,13 @@ typedef struct MacVlan MacVlan;
|
||||
|
||||
#include "macvlan-util.h"
|
||||
#include "netdev.h"
|
||||
#include "set.h"
|
||||
|
||||
struct MacVlan {
|
||||
NetDev meta;
|
||||
|
||||
MacVlanMode mode;
|
||||
Set *match_source_mac;
|
||||
};
|
||||
|
||||
DEFINE_NETDEV_CAST(MACVLAN, MacVlan);
|
||||
|
@ -52,7 +52,9 @@ VLAN.MVRP, config_parse_tristate,
|
||||
VLAN.LooseBinding, config_parse_tristate, 0, offsetof(VLan, loose_binding)
|
||||
VLAN.ReorderHeader, config_parse_tristate, 0, offsetof(VLan, reorder_hdr)
|
||||
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
|
||||
MACVLAN.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
|
||||
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
|
||||
MACVTAP.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
|
||||
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
|
||||
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
|
||||
IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
|
||||
|
@ -9,6 +9,7 @@ static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
|
||||
[NETDEV_MACVLAN_MODE_VEPA] = "vepa",
|
||||
[NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
|
||||
[NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
|
||||
[NETDEV_MACVLAN_MODE_SOURCE] = "source",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
|
||||
|
@ -8,6 +8,7 @@ typedef enum MacVlanMode {
|
||||
NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA,
|
||||
NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE,
|
||||
NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU,
|
||||
NETDEV_MACVLAN_MODE_SOURCE = MACVLAN_MODE_SOURCE,
|
||||
_NETDEV_MACVLAN_MODE_MAX,
|
||||
_NETDEV_MACVLAN_MODE_INVALID = -1
|
||||
} MacVlanMode;
|
||||
|
@ -6,6 +6,7 @@ Id=
|
||||
GVRP=
|
||||
[MACVLAN]
|
||||
Mode=
|
||||
SourceMACAddress=
|
||||
[WireGuard]
|
||||
ListenPort=
|
||||
PrivateKey=
|
||||
@ -14,6 +15,7 @@ FwMark=
|
||||
FirewallMark=
|
||||
[MACVTAP]
|
||||
Mode=
|
||||
SourceMACAddress=
|
||||
[Match]
|
||||
Architecture=
|
||||
Host=
|
||||
|
Loading…
Reference in New Issue
Block a user