From: Susant Sahani Date: Fri, 14 May 2021 05:28:18 +0000 (+0900) Subject: network: bridge-fdb: add support to specify outgoing interface X-Git-Tag: v249-rc1~187^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=af99cdf4d493c2e97bc789e22336c377dad1c6e9;p=thirdparty%2Fsystemd.git network: bridge-fdb: add support to specify outgoing interface --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 64bd036e0c8..f02ec7c9b2f 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2856,6 +2856,13 @@ IPv6Token=prefixstable:2002:da8:1:: device is a VXLAN type device and has route shortcircuit enabled. Defaults to self. + + OutgoingInterface= + + Specifies the name or index of the outgoing interface for the VXLAN device driver to + reach the remote VXLAN tunnel endpoint. Defaults to unset. + + diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index 8000d0ffe4c..115ea5bb14a 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -33,6 +33,8 @@ BridgeFDB *bridge_fdb_free(BridgeFDB *fdb) { } network_config_section_free(fdb->section); + + free(fdb->outgoing_ifname); return mfree(fdb); } @@ -154,6 +156,12 @@ static int bridge_fdb_configure(const BridgeFDB *fdb, Link *link, link_netlink_m return log_link_error_errno(link, r, "Could not append NDA_VLAN attribute: %m"); } + if (fdb->outgoing_ifindex > 0) { + r = sd_netlink_message_append_u32(req, NDA_IFINDEX, fdb->outgoing_ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_IFINDEX attribute: %m"); + } + if (in_addr_is_set(fdb->family, &fdb->destination_addr)) { r = netlink_message_append_in_addr_union(req, NDA_DST, fdb->family, &fdb->destination_addr); if (r < 0) @@ -204,13 +212,38 @@ int link_request_static_bridge_fdb(Link *link) { return 0; } +static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { + Link *out = NULL; + + assert(fdb); + assert(link); + assert(link->manager); + + if (!link_is_ready_to_configure(link, false)) + return false; + + if (fdb->outgoing_ifname) { + if (link_get_by_name(link->manager, fdb->outgoing_ifname, &out) < 0) + return false; + + fdb->outgoing_ifindex = out->ifindex; + } else if (fdb->outgoing_ifindex > 0) { + if (link_get(link->manager, fdb->outgoing_ifindex, &out) < 0) + return false; + } + if (out && !link_is_ready_to_configure(out, false)) + return false; + + return true; +} + int request_process_bridge_fdb(Request *req) { assert(req); assert(req->link); assert(req->fdb); assert(req->type == REQUEST_TYPE_BRIDGE_FDB); - if (!link_is_ready_to_configure(req->link, false)) + if (!bridge_fdb_is_ready_to_configure(req->fdb, req->link)) return 0; return bridge_fdb_configure(req->fdb, req->link, req->netlink_handler); @@ -435,3 +468,59 @@ int config_parse_fdb_ntf_flags( TAKE_PTR(fdb); return 0; } + +int config_parse_fdb_interface( + 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) { + + _cleanup_(bridge_fdb_free_or_set_invalidp) BridgeFDB *fdb = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = bridge_fdb_new_static(network, filename, section_line, &fdb); + if (r < 0) + return log_oom(); + + if (isempty(rvalue)) { + fdb->outgoing_ifname = mfree(fdb->outgoing_ifname); + fdb->outgoing_ifindex = 0; + TAKE_PTR(fdb); + return 0; + } + + r = parse_ifindex(rvalue); + if (r > 0) { + fdb->outgoing_ifname = mfree(fdb->outgoing_ifname); + fdb->outgoing_ifindex = r; + TAKE_PTR(fdb); + return 0; + } + + if (!ifname_valid_full(rvalue, IFNAME_VALID_ALTERNATIVE)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid interface name in %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + r = free_and_strdup(&fdb->outgoing_ifname, rvalue); + if (r < 0) + return log_oom(); + fdb->outgoing_ifindex = 0; + + TAKE_PTR(fdb); + return 0; +} diff --git a/src/network/networkd-bridge-fdb.h b/src/network/networkd-bridge-fdb.h index c091dd7c490..fae7da5bbb2 100644 --- a/src/network/networkd-bridge-fdb.h +++ b/src/network/networkd-bridge-fdb.h @@ -37,6 +37,8 @@ typedef struct BridgeFDB { struct ether_addr mac_addr; union in_addr_union destination_addr; NeighborCacheEntryFlags ntf_flags; + char *outgoing_ifname; + int outgoing_ifindex; } BridgeFDB; BridgeFDB *bridge_fdb_free(BridgeFDB *fdb); @@ -52,3 +54,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vxlan_vni); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_ntf_flags); +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_interface); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 2db2dbe44d8..cfa53503d43 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -306,6 +306,7 @@ BridgeFDB.VLANId, config_parse_fdb_vlan_id, BridgeFDB.Destination, config_parse_fdb_destination, 0, 0 BridgeFDB.VNI, config_parse_fdb_vxlan_vni, 0, 0 BridgeFDB.AssociatedWith, config_parse_fdb_ntf_flags, 0, 0 +BridgeFDB.OutgoingInterface, config_parse_fdb_interface, 0, 0 BridgeMDB.MulticastGroupAddress, config_parse_mdb_group_address, 0, 0 BridgeMDB.VLANId, config_parse_mdb_vlan_id, 0, 0 BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 9cbc9e80888..84717985ed2 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -58,6 +58,7 @@ MACAddress= Destination= VNI= AssociatedWith= +OutgoingInterface= [BridgeMDB] MulticastGroupAddress= VLANId=