2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2014-07-05 15:00:59 +02:00
|
|
|
|
2015-10-05 06:08:00 +02:00
|
|
|
#include <net/if.h>
|
2014-07-05 15:00:59 +02:00
|
|
|
|
2019-10-30 09:02:15 +01:00
|
|
|
#include "bridge.h"
|
2015-10-05 06:08:00 +02:00
|
|
|
#include "netlink-util.h"
|
2019-05-10 16:22:47 +02:00
|
|
|
#include "network-internal.h"
|
2016-11-13 04:59:06 +01:00
|
|
|
#include "networkd-manager.h"
|
2019-05-10 17:02:58 +02:00
|
|
|
#include "string-table.h"
|
2017-05-29 17:20:01 +02:00
|
|
|
#include "vlan-util.h"
|
2015-10-05 06:08:00 +02:00
|
|
|
|
2019-05-10 17:02:58 +02:00
|
|
|
static const char* const multicast_router_table[_MULTICAST_ROUTER_MAX] = {
|
|
|
|
[MULTICAST_ROUTER_NONE] = "no",
|
|
|
|
[MULTICAST_ROUTER_TEMPORARY_QUERY] = "query",
|
|
|
|
[MULTICAST_ROUTER_PERMANENT] = "permanent",
|
|
|
|
[MULTICAST_ROUTER_TEMPORARY] = "temporary",
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router, MulticastRouter, _MULTICAST_ROUTER_INVALID);
|
|
|
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router, multicast_router, MulticastRouter,
|
|
|
|
"Failed to parse bridge multicast router setting");
|
|
|
|
|
2019-04-27 02:22:40 +02:00
|
|
|
/* callback for bridge netdev's parameter set */
|
2018-11-28 21:06:52 +01:00
|
|
|
static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
|
2015-10-05 06:08:00 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(netdev);
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
r = sd_netlink_message_get_errno(m);
|
|
|
|
if (r < 0) {
|
|
|
|
log_netdev_warning_errno(netdev, r, "Bridge parameters could not be set: %m");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-09-30 13:25:25 +02:00
|
|
|
log_netdev_debug(netdev, "Bridge parameters set success");
|
2015-10-05 06:08:00 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
2015-10-05 06:08:00 +02:00
|
|
|
Bridge *b;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(netdev);
|
|
|
|
|
|
|
|
b = BRIDGE(netdev);
|
|
|
|
|
|
|
|
assert(b);
|
|
|
|
|
|
|
|
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, netdev->ifindex);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m");
|
|
|
|
|
|
|
|
r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not set netlink flags: %m");
|
|
|
|
|
|
|
|
r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
|
|
|
|
if (r < 0)
|
2019-01-24 06:33:58 +01:00
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
|
2015-10-05 06:08:00 +02:00
|
|
|
|
|
|
|
r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
|
|
|
|
|
2015-11-03 17:29:42 +01:00
|
|
|
/* convert to jiffes */
|
2016-11-30 11:54:42 +01:00
|
|
|
if (b->forward_delay != USEC_INFINITY) {
|
2015-11-03 17:29:42 +01:00
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BR_FORWARD_DELAY, usec_to_jiffies(b->forward_delay));
|
2015-10-05 06:08:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b->hello_time > 0) {
|
2015-11-03 17:29:42 +01:00
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BR_HELLO_TIME, usec_to_jiffies(b->hello_time));
|
2015-10-05 06:08:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_HELLO_TIME attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b->max_age > 0) {
|
2015-11-03 17:29:42 +01:00
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BR_MAX_AGE, usec_to_jiffies(b->max_age));
|
2015-10-05 06:08:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m");
|
|
|
|
}
|
|
|
|
|
2017-10-11 09:08:05 +02:00
|
|
|
if (b->ageing_time != USEC_INFINITY) {
|
2016-08-31 20:06:23 +02:00
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BR_AGEING_TIME, usec_to_jiffies(b->ageing_time));
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_AGEING_TIME attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b->priority > 0) {
|
|
|
|
r = sd_netlink_message_append_u16(req, IFLA_BR_PRIORITY, b->priority);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m");
|
|
|
|
}
|
|
|
|
|
2017-09-08 12:36:06 +02:00
|
|
|
if (b->group_fwd_mask > 0) {
|
|
|
|
r = sd_netlink_message_append_u16(req, IFLA_BR_GROUP_FWD_MASK, b->group_fwd_mask);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_GROUP_FWD_MASK attribute: %m");
|
|
|
|
}
|
|
|
|
|
2017-05-29 17:20:01 +02:00
|
|
|
if (b->default_pvid != VLANID_INVALID) {
|
2016-08-31 20:06:23 +02:00
|
|
|
r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m");
|
|
|
|
}
|
|
|
|
|
2016-04-18 13:45:52 +02:00
|
|
|
if (b->mcast_querier >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_QUERIER, b->mcast_querier);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_QUERIER attribute: %m");
|
|
|
|
}
|
|
|
|
|
2016-05-15 15:15:20 +02:00
|
|
|
if (b->mcast_snooping >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_SNOOPING, b->mcast_snooping);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m");
|
|
|
|
}
|
|
|
|
|
2016-05-30 17:00:16 +02:00
|
|
|
if (b->vlan_filtering >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BR_VLAN_FILTERING, b->vlan_filtering);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m");
|
|
|
|
}
|
|
|
|
|
2020-03-20 16:09:36 +01:00
|
|
|
if (b->vlan_protocol >= 0) {
|
|
|
|
r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_PROTOCOL, b->vlan_protocol);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_PROTOCOL attribute: %m");
|
|
|
|
}
|
|
|
|
|
2016-08-06 01:44:57 +02:00
|
|
|
if (b->stp >= 0) {
|
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BR_STP_STATE, b->stp);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_STP_STATE attribute: %m");
|
|
|
|
}
|
|
|
|
|
2019-07-24 14:58:57 +02:00
|
|
|
if (b->igmp_version > 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_IGMP_VERSION, b->igmp_version);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_IGMP_VERSION attribute: %m");
|
|
|
|
}
|
|
|
|
|
2015-10-05 06:08:00 +02:00
|
|
|
r = sd_netlink_message_close_container(req);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
|
|
|
|
|
|
|
|
r = sd_netlink_message_close_container(req);
|
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
|
|
|
|
|
2018-11-28 21:06:52 +01:00
|
|
|
r = netlink_call_async(netdev->manager->rtnl, NULL, req, netdev_bridge_set_handler,
|
|
|
|
netdev_destroy_callback, netdev);
|
2015-10-05 06:08:00 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
|
|
|
|
|
|
|
|
netdev_ref(netdev);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2014-07-05 15:00:59 +02:00
|
|
|
|
2019-05-10 16:22:47 +02:00
|
|
|
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
assert(link);
|
|
|
|
assert(link->ifname);
|
|
|
|
|
|
|
|
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
r = sd_netlink_message_get_errno(m);
|
|
|
|
if (r < 0) {
|
|
|
|
log_link_warning_errno(link, r, "Could not set bridge interface: %m");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int link_set_bridge(Link *link) {
|
|
|
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->network);
|
|
|
|
|
|
|
|
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
|
|
|
|
|
|
|
r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not set message family: %m");
|
|
|
|
|
|
|
|
r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
|
|
|
|
|
|
|
|
if (link->network->use_bpdu >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->hairpin >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->fast_leave >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
|
|
|
|
}
|
|
|
|
|
2020-07-14 20:40:26 +02:00
|
|
|
if (link->network->allow_port_to_be_root >= 0) {
|
2019-05-10 16:22:47 +02:00
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->unicast_flood >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->multicast_flood >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->multicast_to_unicast >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->neighbor_suppression >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->learning >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->bridge_proxy_arp >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->bridge_proxy_arp_wifi >= 0) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->cost != 0) {
|
|
|
|
r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
|
|
|
|
r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
|
|
|
|
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_netlink_message_close_container(req);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
|
|
|
|
|
|
|
|
r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bridge_handler,
|
|
|
|
link_netlink_destroy_callback, link);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
|
|
|
|
|
|
|
link_ref(link);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2019-07-24 14:58:57 +02:00
|
|
|
int config_parse_bridge_igmp_version(
|
|
|
|
const char *unit,
|
|
|
|
const char *filename,
|
|
|
|
unsigned line,
|
|
|
|
const char *section,
|
|
|
|
unsigned section_line,
|
|
|
|
const char *lvalue,
|
|
|
|
int ltype,
|
|
|
|
const char *rvalue,
|
|
|
|
void *data,
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
Bridge *b = userdata;
|
|
|
|
uint8_t u;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
assert(data);
|
|
|
|
|
|
|
|
if (isempty(rvalue)) {
|
|
|
|
b->igmp_version = 0; /* 0 means unset. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = safe_atou8(rvalue, &u);
|
|
|
|
if (r < 0) {
|
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
2019-07-26 03:59:36 +02:00
|
|
|
"Failed to parse bridge's multicast IGMP version number '%s', ignoring assignment: %m",
|
2019-07-24 14:58:57 +02:00
|
|
|
rvalue);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!IN_SET(u, 2, 3)) {
|
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
2019-07-26 03:59:36 +02:00
|
|
|
"Invalid bridge's multicast IGMP version number '%s', ignoring assignment.", rvalue);
|
2019-07-24 14:58:57 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
b->igmp_version = u;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-18 13:45:52 +02:00
|
|
|
static void bridge_init(NetDev *n) {
|
|
|
|
Bridge *b;
|
|
|
|
|
|
|
|
b = BRIDGE(n);
|
|
|
|
|
|
|
|
assert(b);
|
|
|
|
|
|
|
|
b->mcast_querier = -1;
|
2016-05-15 15:15:20 +02:00
|
|
|
b->mcast_snooping = -1;
|
2016-05-30 17:00:16 +02:00
|
|
|
b->vlan_filtering = -1;
|
2020-03-20 16:09:36 +01:00
|
|
|
b->vlan_protocol = -1;
|
2016-08-06 01:44:57 +02:00
|
|
|
b->stp = -1;
|
2017-05-29 17:20:01 +02:00
|
|
|
b->default_pvid = VLANID_INVALID;
|
2016-11-30 11:54:42 +01:00
|
|
|
b->forward_delay = USEC_INFINITY;
|
2017-10-11 09:08:05 +02:00
|
|
|
b->ageing_time = USEC_INFINITY;
|
2016-04-18 13:45:52 +02:00
|
|
|
}
|
|
|
|
|
2014-07-06 14:07:34 +02:00
|
|
|
const NetDevVTable bridge_vtable = {
|
2014-07-16 13:17:10 +02:00
|
|
|
.object_size = sizeof(Bridge),
|
2016-04-18 13:45:52 +02:00
|
|
|
.init = bridge_init,
|
2019-11-22 11:43:26 +01:00
|
|
|
.sections = NETDEV_COMMON_SECTIONS "Bridge\0",
|
2015-10-05 06:08:00 +02:00
|
|
|
.post_create = netdev_bridge_post_create,
|
2014-07-16 13:17:10 +02:00
|
|
|
.create_type = NETDEV_CREATE_MASTER,
|
2014-07-06 14:07:34 +02:00
|
|
|
};
|