Merge pull request #21865 from yuwata/network-sr-iov

udev/net: support configuring SR-IOV virtual functions through .link file
This commit is contained in:
Luca Boccassi
2022-01-19 22:38:00 +00:00
committed by GitHub
51 changed files with 1281 additions and 806 deletions
+5 -5
View File
@@ -46,15 +46,15 @@ static L2tpSession* l2tp_session_free(L2tpSession *s) {
if (s->tunnel && s->section)
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
network_config_section_free(s->section);
config_section_free(s->section);
free(s->name);
return mfree(s);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(L2tpSession, l2tp_session_free);
static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
int r;
@@ -63,7 +63,7 @@ static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -83,7 +83,7 @@ static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned
.section = TAKE_PTR(n),
};
r = ordered_hashmap_ensure_put(&t->sessions_by_section, &network_config_hash_ops, s->section, s);
r = ordered_hashmap_ensure_put(&t->sessions_by_section, &config_section_hash_ops, s->section, s);
if (r < 0)
return r;
+1 -1
View File
@@ -34,7 +34,7 @@ typedef struct L2tpTunnel L2tpTunnel;
typedef struct L2tpSession {
L2tpTunnel *tunnel;
NetworkConfigSection *section;
ConfigSection *section;
char *name;
+15 -15
View File
@@ -43,16 +43,16 @@ static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c
if (c->macsec && c->section)
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
network_config_section_free(c->section);
config_section_free(c->section);
security_association_clear(&c->sa);
return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
static int macsec_receive_association_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveAssociation **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(macsec_receive_association_freep) ReceiveAssociation *c = NULL;
int r;
@@ -61,7 +61,7 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -82,7 +82,7 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
security_association_init(&c->sa);
r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &network_config_hash_ops, c->section, c);
r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &config_section_hash_ops, c->section, c);
if (r < 0)
return r;
@@ -103,12 +103,12 @@ static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section);
}
network_config_section_free(c->section);
config_section_free(c->section);
return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) {
ReceiveChannel *c;
@@ -129,7 +129,7 @@ static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **
}
static int macsec_receive_channel_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveChannel **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(macsec_receive_channel_freep) ReceiveChannel *c = NULL;
int r;
@@ -138,7 +138,7 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -154,7 +154,7 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
c->section = TAKE_PTR(n);
r = ordered_hashmap_ensure_put(&s->receive_channels_by_section, &network_config_hash_ops, c->section, c);
r = ordered_hashmap_ensure_put(&s->receive_channels_by_section, &config_section_hash_ops, c->section, c);
if (r < 0)
return r;
@@ -170,16 +170,16 @@ static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation
if (a->macsec && a->section)
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
network_config_section_free(a->section);
config_section_free(a->section);
security_association_clear(&a->sa);
return mfree(a);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
static int macsec_transmit_association_new_static(MACsec *s, const char *filename, unsigned section_line, TransmitAssociation **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(macsec_transmit_association_freep) TransmitAssociation *a = NULL;
int r;
@@ -188,7 +188,7 @@ static int macsec_transmit_association_new_static(MACsec *s, const char *filenam
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -209,7 +209,7 @@ static int macsec_transmit_association_new_static(MACsec *s, const char *filenam
security_association_init(&a->sa);
r = ordered_hashmap_ensure_put(&s->transmit_associations_by_section, &network_config_hash_ops, a->section, a);
r = ordered_hashmap_ensure_put(&s->transmit_associations_by_section, &config_section_hash_ops, a->section, a);
if (r < 0)
return r;
+3 -3
View File
@@ -39,14 +39,14 @@ typedef struct SecurityAssociation {
typedef struct TransmitAssociation {
MACsec *macsec;
NetworkConfigSection *section;
ConfigSection *section;
SecurityAssociation sa;
} TransmitAssociation;
typedef struct ReceiveAssociation {
MACsec *macsec;
NetworkConfigSection *section;
ConfigSection *section;
MACsecSCI sci;
SecurityAssociation sa;
@@ -54,7 +54,7 @@ typedef struct ReceiveAssociation {
typedef struct ReceiveChannel {
MACsec *macsec;
NetworkConfigSection *section;
ConfigSection *section;
MACsecSCI sci;
ReceiveAssociation *rxsa[MACSEC_MAX_ASSOCIATION_NUMBER];
+5 -5
View File
@@ -47,7 +47,7 @@ static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
hashmap_remove(peer->wireguard->peers_by_section, peer->section);
}
network_config_section_free(peer->section);
config_section_free(peer->section);
while ((mask = peer->ipmasks)) {
LIST_REMOVE(ipmasks, peer->ipmasks, mask);
@@ -65,10 +65,10 @@ static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
return mfree(peer);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(WireguardPeer, wireguard_peer_free);
static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigned section_line, WireguardPeer **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(wireguard_peer_freep) WireguardPeer *peer = NULL;
int r;
@@ -77,7 +77,7 @@ static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigne
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -99,7 +99,7 @@ static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigne
LIST_PREPEND(peers, w->peers, peer);
r = hashmap_ensure_put(&w->peers_by_section, &network_config_hash_ops, peer->section, peer);
r = hashmap_ensure_put(&w->peers_by_section, &config_section_hash_ops, peer->section, peer);
if (r < 0)
return r;
+1 -1
View File
@@ -24,7 +24,7 @@ typedef struct WireguardIPmask {
typedef struct WireguardPeer {
Wireguard *wireguard;
NetworkConfigSection *section;
ConfigSection *section;
uint8_t public_key[WG_KEY_LEN];
uint8_t preshared_key[WG_KEY_LEN];
+5 -5
View File
@@ -21,14 +21,14 @@ AddressLabel *address_label_free(AddressLabel *label) {
hashmap_remove(label->network->address_labels_by_section, label->section);
}
network_config_section_free(label->section);
config_section_free(label->section);
return mfree(label);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(AddressLabel, address_label_free);
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(address_label_freep) AddressLabel *label = NULL;
int r;
@@ -37,7 +37,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -57,7 +57,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
.label = UINT32_MAX,
};
r = hashmap_ensure_put(&network->address_labels_by_section, &network_config_hash_ops, label->section, label);
r = hashmap_ensure_put(&network->address_labels_by_section, &config_section_hash_ops, label->section, label);
if (r < 0)
return r;
+1 -1
View File
@@ -13,7 +13,7 @@ typedef struct Request Request;
typedef struct AddressLabel {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
uint32_t label;
struct in6_addr prefix;
+4 -4
View File
@@ -77,7 +77,7 @@ int address_new(Address **ret) {
}
static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(address_freep) Address *address = NULL;
int r;
@@ -86,7 +86,7 @@ static int address_new_static(Network *network, const char *filename, unsigned s
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -107,7 +107,7 @@ static int address_new_static(Network *network, const char *filename, unsigned s
address->section = TAKE_PTR(n);
address->source = NETWORK_CONFIG_SOURCE_STATIC;
r = ordered_hashmap_ensure_put(&network->addresses_by_section, &network_config_hash_ops, address->section, address);
r = ordered_hashmap_ensure_put(&network->addresses_by_section, &config_section_hash_ops, address->section, address);
if (r < 0)
return r;
@@ -134,7 +134,7 @@ Address *address_free(Address *address) {
sd_ipv4acd_unref(address->acd);
network_config_section_free(address->section);
config_section_free(address->section);
free(address->label);
return mfree(address);
}
+2 -2
View File
@@ -22,7 +22,7 @@ typedef int (*address_ready_callback_t)(Address *address);
struct Address {
Link *link;
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
NetworkConfigSource source;
NetworkConfigState state;
union in_addr_union provider; /* DHCP server or router address */
@@ -72,7 +72,7 @@ int address_dup(const Address *src, Address **ret);
bool address_is_ready(const Address *a);
void address_set_broadcast(Address *a);
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Address, address_free);
int link_drop_addresses(Link *link);
int link_drop_foreign_addresses(Link *link);
+5 -5
View File
@@ -32,13 +32,13 @@ BridgeFDB *bridge_fdb_free(BridgeFDB *fdb) {
hashmap_remove(fdb->network->bridge_fdb_entries_by_section, fdb->section);
}
network_config_section_free(fdb->section);
config_section_free(fdb->section);
free(fdb->outgoing_ifname);
return mfree(fdb);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(BridgeFDB, bridge_fdb_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeFDB, bridge_fdb_free);
/* create a new FDB entry or get an existing one. */
static int bridge_fdb_new_static(
@@ -47,7 +47,7 @@ static int bridge_fdb_new_static(
unsigned section_line,
BridgeFDB **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(bridge_fdb_freep) BridgeFDB *fdb = NULL;
int r;
@@ -56,7 +56,7 @@ static int bridge_fdb_new_static(
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -83,7 +83,7 @@ static int bridge_fdb_new_static(
.ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
};
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &network_config_hash_ops, fdb->section, fdb);
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &config_section_hash_ops, fdb->section, fdb);
if (r < 0)
return r;
+1 -1
View File
@@ -27,7 +27,7 @@ typedef enum NeighborCacheEntryFlags {
typedef struct BridgeFDB {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
uint32_t vni;
+5 -5
View File
@@ -24,12 +24,12 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb) {
hashmap_remove(mdb->network->bridge_mdb_entries_by_section, mdb->section);
}
network_config_section_free(mdb->section);
config_section_free(mdb->section);
return mfree(mdb);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(BridgeMDB, bridge_mdb_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeMDB, bridge_mdb_free);
/* create a new MDB entry or get an existing one. */
static int bridge_mdb_new_static(
@@ -38,7 +38,7 @@ static int bridge_mdb_new_static(
unsigned section_line,
BridgeMDB **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(bridge_mdb_freep) BridgeMDB *mdb = NULL;
int r;
@@ -47,7 +47,7 @@ static int bridge_mdb_new_static(
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -72,7 +72,7 @@ static int bridge_mdb_new_static(
.section = TAKE_PTR(n),
};
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &network_config_hash_ops, mdb->section, mdb);
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &config_section_hash_ops, mdb->section, mdb);
if (r < 0)
return r;
+1 -1
View File
@@ -13,7 +13,7 @@ typedef struct Request Request;
typedef struct BridgeMDB {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
int family;
union in_addr_union group_addr;
@@ -7,7 +7,7 @@
#include "networkd-network.h"
#include "networkd-util.h"
DEFINE_NETWORK_SECTION_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
if (!static_lease)
@@ -16,7 +16,7 @@ DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
if (static_lease->network && static_lease->section)
hashmap_remove(static_lease->network->dhcp_static_leases_by_section, static_lease->section);
network_config_section_free(static_lease->section);
config_section_free(static_lease->section);
free(static_lease->client_id);
return mfree(static_lease);
}
@@ -35,7 +35,7 @@ static int dhcp_static_lease_new(DHCPStaticLease **ret) {
}
static int lease_new_static(Network *network, const char *filename, unsigned section_line, DHCPStaticLease **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(dhcp_static_lease_freep) DHCPStaticLease *static_lease = NULL;
int r;
@@ -44,7 +44,7 @@ static int lease_new_static(Network *network, const char *filename, unsigned sec
assert(section_line > 0);
assert(ret);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -60,7 +60,7 @@ static int lease_new_static(Network *network, const char *filename, unsigned sec
static_lease->network = network;
static_lease->section = TAKE_PTR(n);
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &network_config_hash_ops, static_lease->section, static_lease);
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &config_section_hash_ops, static_lease->section, static_lease);
if (r < 0)
return r;
@@ -8,11 +8,11 @@
#include "in-addr-util.h"
typedef struct Network Network;
typedef struct NetworkConfigSection NetworkConfigSection;
typedef struct ConfigSection ConfigSection;
typedef struct DHCPStaticLease {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
struct in_addr address;
uint8_t *client_id;
+2
View File
@@ -2549,6 +2549,8 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
if (r < 0)
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
else
log_link_debug(link, "Found driver: %s", strna(link->driver));
if (streq_ptr(link->driver, "dsa")) {
uint32_t dsa_master_ifindex;
+5 -5
View File
@@ -19,7 +19,7 @@ Neighbor *neighbor_free(Neighbor *neighbor) {
hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
}
network_config_section_free(neighbor->section);
config_section_free(neighbor->section);
if (neighbor->link)
set_remove(neighbor->link->neighbors, neighbor);
@@ -27,10 +27,10 @@ Neighbor *neighbor_free(Neighbor *neighbor) {
return mfree(neighbor);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Neighbor, neighbor_free);
static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
int r;
@@ -39,7 +39,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -60,7 +60,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
.source = NETWORK_CONFIG_SOURCE_STATIC,
};
r = hashmap_ensure_put(&network->neighbors_by_section, &network_config_hash_ops, neighbor->section, neighbor);
r = hashmap_ensure_put(&network->neighbors_by_section, &config_section_hash_ops, neighbor->section, neighbor);
if (r < 0)
return r;
+1 -1
View File
@@ -18,7 +18,7 @@ typedef struct Request Request;
typedef struct Neighbor {
Network *network;
Link *link;
NetworkConfigSection *section;
ConfigSection *section;
NetworkConfigSource source;
NetworkConfigState state;
+9 -9
View File
@@ -73,15 +73,15 @@ Link.Unmanaged, config_parse_bool,
Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy)
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
Link.RequiredFamilyForOnline, config_parse_required_family_for_online, 0, offsetof(Network, required_family_for_online)
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, 0
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, 0
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, 0
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, 0
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, 0
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, 0
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, 0
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, offsetof(Network, sr_iov_by_section)
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, offsetof(Network, sr_iov_by_section)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.KeepMaster, config_parse_bool, 0, offsetof(Network, keep_master)
Network.BatmanAdvanced, config_parse_ifname, 0, offsetof(Network, batadv_name)
+3 -1
View File
@@ -321,7 +321,9 @@ int network_verify(Network *network) {
network_drop_invalid_route_prefixes(network);
network_drop_invalid_routing_policy_rules(network);
network_drop_invalid_traffic_control(network);
network_drop_invalid_sr_iov(network);
r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
if (r < 0)
return r;
network_drop_invalid_static_leases(network);
network_adjust_dhcp_server(network);
+5 -5
View File
@@ -27,7 +27,7 @@ NextHop *nexthop_free(NextHop *nexthop) {
hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
}
network_config_section_free(nexthop->section);
config_section_free(nexthop->section);
if (nexthop->link) {
set_remove(nexthop->link->nexthops, nexthop);
@@ -48,7 +48,7 @@ NextHop *nexthop_free(NextHop *nexthop) {
return mfree(nexthop);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(NextHop, nexthop_free);
static int nexthop_new(NextHop **ret) {
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
@@ -68,7 +68,7 @@ static int nexthop_new(NextHop **ret) {
}
static int nexthop_new_static(Network *network, const char *filename, unsigned section_line, NextHop **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
int r;
@@ -77,7 +77,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -96,7 +96,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
nexthop->section = TAKE_PTR(n);
nexthop->source = NETWORK_CONFIG_SOURCE_STATIC;
r = hashmap_ensure_put(&network->nexthops_by_section, &network_config_hash_ops, nexthop->section, nexthop);
r = hashmap_ensure_put(&network->nexthops_by_section, &config_section_hash_ops, nexthop->section, nexthop);
if (r < 0)
return r;
+1 -1
View File
@@ -22,7 +22,7 @@ typedef struct NextHop {
Network *network;
Manager *manager;
Link *link;
NetworkConfigSection *section;
ConfigSection *section;
NetworkConfigSource source;
NetworkConfigState state;
+10 -10
View File
@@ -69,16 +69,16 @@ Prefix *prefix_free(Prefix *prefix) {
hashmap_remove(prefix->network->prefixes_by_section, prefix->section);
}
network_config_section_free(prefix->section);
config_section_free(prefix->section);
set_free(prefix->tokens);
return mfree(prefix);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix, prefix_free);
static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(prefix_freep) Prefix *prefix = NULL;
int r;
@@ -87,7 +87,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -111,7 +111,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
.address_auto_configuration = true,
};
r = hashmap_ensure_put(&network->prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
r = hashmap_ensure_put(&network->prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
if (r < 0)
return r;
@@ -128,15 +128,15 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix) {
hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section);
}
network_config_section_free(prefix->section);
config_section_free(prefix->section);
return mfree(prefix);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix, route_prefix_free);
static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
int r;
@@ -145,7 +145,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -166,7 +166,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
.lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
};
r = hashmap_ensure_put(&network->route_prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
r = hashmap_ensure_put(&network->route_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
if (r < 0)
return r;
+2 -2
View File
@@ -29,7 +29,7 @@ typedef enum RADVPrefixDelegation {
typedef struct Prefix {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
struct in6_addr prefix;
uint8_t prefixlen;
@@ -46,7 +46,7 @@ typedef struct Prefix {
typedef struct RoutePrefix {
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
struct in6_addr prefix;
uint8_t prefixlen;
+4 -4
View File
@@ -47,7 +47,7 @@ int route_new(Route **ret) {
}
static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(route_freep) Route *route = NULL;
int r;
@@ -56,7 +56,7 @@ static int route_new_static(Network *network, const char *filename, unsigned sec
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -78,7 +78,7 @@ static int route_new_static(Network *network, const char *filename, unsigned sec
route->section = TAKE_PTR(n);
route->source = NETWORK_CONFIG_SOURCE_STATIC;
r = hashmap_ensure_put(&network->routes_by_section, &network_config_hash_ops, route->section, route);
r = hashmap_ensure_put(&network->routes_by_section, &config_section_hash_ops, route->section, route);
if (r < 0)
return r;
@@ -95,7 +95,7 @@ Route *route_free(Route *route) {
hashmap_remove(route->network->routes_by_section, route->section);
}
network_config_section_free(route->section);
config_section_free(route->section);
if (route->link)
set_remove(route->link->routes, route);
+2 -2
View File
@@ -19,7 +19,7 @@ typedef struct Route {
Link *link;
Manager *manager;
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
NetworkConfigSource source;
NetworkConfigState state;
union in_addr_union provider; /* DHCP server or router address */
@@ -74,7 +74,7 @@ extern const struct hash_ops route_hash_ops;
int route_new(Route **ret);
Route *route_free(Route *route);
DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_free);
int route_dup(const Route *src, Route **ret);
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
+5 -5
View File
@@ -54,14 +54,14 @@ RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
if (rule->manager)
set_remove(rule->manager->rules, rule);
network_config_section_free(rule->section);
config_section_free(rule->section);
free(rule->iif);
free(rule->oif);
return mfree(rule);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
static int routing_policy_rule_new(RoutingPolicyRule **ret) {
RoutingPolicyRule *rule;
@@ -86,7 +86,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) {
static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
int r;
assert(network);
@@ -94,7 +94,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -113,7 +113,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
rule->source = NETWORK_CONFIG_SOURCE_STATIC;
rule->protocol = RTPROT_STATIC;
r = hashmap_ensure_put(&network->rules_by_section, &network_config_hash_ops, rule->section, rule);
r = hashmap_ensure_put(&network->rules_by_section, &config_section_hash_ops, rule->section, rule);
if (r < 0)
return r;
+1 -1
View File
@@ -17,7 +17,7 @@ typedef struct Request Request;
typedef struct RoutingPolicyRule {
Manager *manager;
Network *network;
NetworkConfigSection *section;
ConfigSection *section;
NetworkConfigSource source;
NetworkConfigState state;
+8 -450
View File
@@ -1,82 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright © 2020 VMware, Inc. */
#include "alloc-util.h"
#include "netlink-util.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-sriov.h"
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
static int sr_iov_new(SRIOV **ret) {
SRIOV *sr_iov;
sr_iov = new(SRIOV, 1);
if (!sr_iov)
return -ENOMEM;
*sr_iov = (SRIOV) {
.vf = UINT32_MAX,
.vlan_proto = ETH_P_8021Q,
.vf_spoof_check_setting = -1,
.trust = -1,
.query_rss = -1,
.link_state = _SR_IOV_LINK_STATE_INVALID,
};
*ret = TAKE_PTR(sr_iov);
return 0;
}
static int sr_iov_new_static(Network *network, const char *filename, unsigned section_line, SRIOV **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(sr_iov_freep) SRIOV *sr_iov = NULL;
SRIOV *existing = NULL;
int r;
assert(network);
assert(ret);
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
if (r < 0)
return r;
existing = ordered_hashmap_get(network->sr_iov_by_section, n);
if (existing) {
*ret = existing;
return 0;
}
r = sr_iov_new(&sr_iov);
if (r < 0)
return r;
sr_iov->network = network;
sr_iov->section = TAKE_PTR(n);
r = ordered_hashmap_ensure_put(&network->sr_iov_by_section, &network_config_hash_ops, sr_iov->section, sr_iov);
if (r < 0)
return r;
*ret = TAKE_PTR(sr_iov);
return 0;
}
SRIOV *sr_iov_free(SRIOV *sr_iov) {
if (!sr_iov)
return NULL;
if (sr_iov->network && sr_iov->section)
ordered_hashmap_remove(sr_iov->network->sr_iov_by_section, sr_iov->section);
network_config_section_free(sr_iov->section);
return mfree(sr_iov);
}
static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
@@ -117,104 +45,16 @@ static int sr_iov_configure(Link *link, SRIOV *sr_iov) {
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");
return r;
r = sd_netlink_message_open_container(req, IFLA_VFINFO_LIST);
r = sr_iov_set_netlink_message(sr_iov, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not open IFLA_VFINFO_LIST container: %m");
r = sd_netlink_message_open_container(req, IFLA_VF_INFO);
if (r < 0)
return log_link_error_errno(link, r, "Could not open IFLA_VF_INFO container: %m");
if (!ether_addr_is_null(&sr_iov->mac)) {
struct ifla_vf_mac ivm = {
.vf = sr_iov->vf,
};
memcpy(ivm.mac, &sr_iov->mac, ETH_ALEN);
r = sd_netlink_message_append_data(req, IFLA_VF_MAC, &ivm, sizeof(struct ifla_vf_mac));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_MAC: %m");
}
if (sr_iov->vf_spoof_check_setting >= 0) {
struct ifla_vf_spoofchk ivs = {
.vf = sr_iov->vf,
.setting = sr_iov->vf_spoof_check_setting,
};
r = sd_netlink_message_append_data(req, IFLA_VF_SPOOFCHK, &ivs, sizeof(struct ifla_vf_spoofchk));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_SPOOFCHK: %m");
}
if (sr_iov->query_rss >= 0) {
struct ifla_vf_rss_query_en ivs = {
.vf = sr_iov->vf,
.setting = sr_iov->query_rss,
};
r = sd_netlink_message_append_data(req, IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(struct ifla_vf_rss_query_en));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_RSS_QUERY_EN: %m");
}
if (sr_iov->trust >= 0) {
struct ifla_vf_trust ivt = {
.vf = sr_iov->vf,
.setting = sr_iov->trust,
};
r = sd_netlink_message_append_data(req, IFLA_VF_TRUST, &ivt, sizeof(struct ifla_vf_trust));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_TRUST: %m");
}
if (sr_iov->link_state >= 0) {
struct ifla_vf_link_state ivl = {
.vf = sr_iov->vf,
.link_state = sr_iov->link_state,
};
r = sd_netlink_message_append_data(req, IFLA_VF_LINK_STATE, &ivl, sizeof(struct ifla_vf_link_state));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_LINK_STATE: %m");
}
if (sr_iov->vlan > 0) {
/* Because of padding, first the buffer must be initialized with 0. */
struct ifla_vf_vlan_info ivvi = {};
ivvi.vf = sr_iov->vf;
ivvi.vlan = sr_iov->vlan;
ivvi.qos = sr_iov->qos;
ivvi.vlan_proto = htobe16(sr_iov->vlan_proto);
r = sd_netlink_message_open_container(req, IFLA_VF_VLAN_LIST);
if (r < 0)
return log_link_error_errno(link, r, "Could not open IFLA_VF_VLAN_LIST container: %m");
r = sd_netlink_message_append_data(req, IFLA_VF_VLAN_INFO, &ivvi, sizeof(struct ifla_vf_vlan_info));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_VF_VLAN_INFO: %m");
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not close IFLA_VF_VLAN_LIST container: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not close IFLA_VF_INFO container: %m");
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not close IFLA_VFINFO_LIST container: %m");
return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, sr_iov_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return r;
link_ref(link);
link->sr_iov_messages++;
@@ -239,7 +79,9 @@ int link_configure_sr_iov(Link *link) {
ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
r = sr_iov_configure(link, sr_iov);
if (r < 0)
return r;
return log_link_warning_errno(link, r,
"Failed to configure SR-IOV virtual function %"PRIu32": %m",
sr_iov->vf);
}
if (link->sr_iov_messages == 0)
@@ -249,287 +91,3 @@ int link_configure_sr_iov(Link *link) {
return 0;
}
static int sr_iov_section_verify(SRIOV *sr_iov) {
assert(sr_iov);
if (section_is_invalid(sr_iov->section))
return -EINVAL;
if (sr_iov->vf == UINT32_MAX)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: [SRIOV] section without VirtualFunction= field configured. "
"Ignoring [SRIOV] section from line %u.",
sr_iov->section->filename, sr_iov->section->line);
return 0;
}
void network_drop_invalid_sr_iov(Network *network) {
SRIOV *sr_iov;
assert(network);
ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
if (sr_iov_section_verify(sr_iov) < 0)
sr_iov_free(sr_iov);
}
int config_parse_sr_iov_uint32(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
Network *network = data;
uint32_t k;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
if (streq(lvalue, "VirtualFunction"))
sr_iov->vf = UINT32_MAX;
else if (streq(lvalue, "VLANId"))
sr_iov->vlan = 0;
else if (streq(lvalue, "QualityOfService"))
sr_iov->qos = 0;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "VLANId")) {
if (k == 0 || k > 4095) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV VLANId: %d", k);
return 0;
}
sr_iov->vlan = k;
} else if (streq(lvalue, "VirtualFunction")) {
if (k >= INT_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV virtual function: %d", k);
return 0;
}
sr_iov->vf = k;
} else if (streq(lvalue, "QualityOfService"))
sr_iov->qos = k;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_vlan_proto(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
Network *network = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue) || streq(rvalue, "802.1Q"))
sr_iov->vlan_proto = ETH_P_8021Q;
else if (streq(rvalue, "802.1ad"))
sr_iov->vlan_proto = ETH_P_8021AD;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_link_state(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
Network *network = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
if (r < 0)
return r;
/* Unfortunately, SR_IOV_LINK_STATE_DISABLE is 2, not 0. So, we cannot use
* DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN() macro. */
if (isempty(rvalue)) {
sr_iov->link_state = _SR_IOV_LINK_STATE_INVALID;
TAKE_PTR(sr_iov);
return 0;
}
if (streq(rvalue, "auto")) {
sr_iov->link_state = SR_IOV_LINK_STATE_AUTO;
TAKE_PTR(sr_iov);
return 0;
}
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
sr_iov->link_state = r ? SR_IOV_LINK_STATE_ENABLE : SR_IOV_LINK_STATE_DISABLE;
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_boolean(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
Network *network = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
if (streq(lvalue, "MACSpoofCheck"))
sr_iov->vf_spoof_check_setting = -1;
else if (streq(lvalue, "QueryReceiveSideScaling"))
sr_iov->query_rss = -1;
else if (streq(lvalue, "Trust"))
sr_iov->trust = -1;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse '%s=', ignoring: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "MACSpoofCheck"))
sr_iov->vf_spoof_check_setting = r;
else if (streq(lvalue, "QueryReceiveSideScaling"))
sr_iov->query_rss = r;
else if (streq(lvalue, "Trust"))
sr_iov->trust = r;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_mac(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
Network *network = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
sr_iov->mac = ETHER_ADDR_NULL;
TAKE_PTR(sr_iov);
return 0;
}
r = parse_ether_addr(rvalue, &sr_iov->mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
TAKE_PTR(sr_iov);
return 0;
}
+2 -39
View File
@@ -2,45 +2,8 @@
* Copyright © 2020 VMware, Inc. */
#pragma once
#include <linux/if_link.h>
#include "netif-sriov.h"
#include "conf-parser.h"
#include "ether-addr-util.h"
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
typedef struct Link Link;
typedef enum SRIOVLinkState {
SR_IOV_LINK_STATE_AUTO = IFLA_VF_LINK_STATE_AUTO,
SR_IOV_LINK_STATE_ENABLE = IFLA_VF_LINK_STATE_ENABLE,
SR_IOV_LINK_STATE_DISABLE = IFLA_VF_LINK_STATE_DISABLE,
_SR_IOV_LINK_STATE_MAX,
_SR_IOV_LINK_STATE_INVALID = -EINVAL,
} SRIOVLinkState;
typedef struct SRIOV {
NetworkConfigSection *section;
Network *network;
uint32_t vf; /* 0 - 2147483646 */
uint32_t vlan; /* 0 - 4095, 0 disables VLAN filter */
uint32_t qos;
uint16_t vlan_proto; /* ETH_P_8021Q or ETH_P_8021AD */
int vf_spoof_check_setting;
int query_rss;
int trust;
SRIOVLinkState link_state;
struct ether_addr mac;
} SRIOV;
SRIOV *sr_iov_free(SRIOV *sr_iov);
int link_configure_sr_iov(Link *link);
void network_drop_invalid_sr_iov(Network *network);
DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_uint32);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_link_state);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_vlan_proto);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_mac);
-44
View File
@@ -243,50 +243,6 @@ int config_parse_mud_url(
return free_and_replace(*url, unescaped);
}
static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
siphash24_compress_string(c->filename, state);
siphash24_compress(&c->line, sizeof(c->line), state);
}
static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
int r;
r = strcmp(x->filename, y->filename);
if (r != 0)
return r;
return CMP(x->line, y->line);
}
DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
NetworkConfigSection *cs;
cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
if (!cs)
return -ENOMEM;
strcpy(cs->filename, filename);
cs->line = line;
*s = TAKE_PTR(cs);
return 0;
}
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
NetworkConfigSection *cs;
unsigned n = 0;
void *entry;
HASHMAP_FOREACH_KEY(entry, cs, hashmap)
if (n < cs->line)
n = cs->line;
return n + 1;
}
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
const char *err_msg = NULL;
-37
View File
@@ -13,12 +13,6 @@
typedef struct Link Link;
typedef struct NetworkConfigSection {
unsigned line;
bool invalid;
char filename[];
} NetworkConfigSection;
typedef enum NetworkConfigSource {
NETWORK_CONFIG_SOURCE_FOREIGN, /* configured by kernel */
NETWORK_CONFIG_SOURCE_STATIC,
@@ -141,37 +135,6 @@ AddressFamily dhcp_deprecated_address_family_from_string(const char *s) _pure_;
const char *dhcp_lease_server_type_to_string(sd_dhcp_lease_server_type_t t) _const_;
sd_dhcp_lease_server_type_t dhcp_lease_server_type_from_string(const char *s) _pure_;
static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
return mfree(cs);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
extern const struct hash_ops network_config_hash_ops;
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
static inline bool section_is_invalid(NetworkConfigSection *section) {
/* If this returns false, then it does _not_ mean the section is valid. */
if (!section)
return false;
return section->invalid;
}
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
static inline type* free_func##_or_set_invalid(type *p) { \
assert(p); \
\
if (p->section) \
p->section->invalid = true; \
else \
free_func(p); \
return NULL; \
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
+4 -4
View File
@@ -77,7 +77,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
}
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(qdisc_freep) QDisc *qdisc = NULL;
TrafficControl *existing;
QDisc *q = NULL;
@@ -88,7 +88,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -126,7 +126,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
qdisc->network = network;
qdisc->section = TAKE_PTR(n);
r = ordered_hashmap_ensure_put(&network->tc_by_section, &network_config_hash_ops, qdisc->section, TC(qdisc));
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, qdisc->section, TC(qdisc));
if (r < 0)
return r;
@@ -141,7 +141,7 @@ QDisc* qdisc_free(QDisc *qdisc) {
if (qdisc->network && qdisc->section)
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
network_config_section_free(qdisc->section);
config_section_free(qdisc->section);
free(qdisc->tca_kind);
return mfree(qdisc);
+2 -2
View File
@@ -37,7 +37,7 @@ typedef enum QDiscKind {
typedef struct QDisc {
TrafficControl meta;
NetworkConfigSection *section;
ConfigSection *section;
Network *network;
int family;
@@ -80,7 +80,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
int qdisc_configure(Link *link, QDisc *qdisc);
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
DEFINE_NETWORK_SECTION_FUNCTIONS(QDisc, qdisc_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_free);
DEFINE_TC_CAST(QDISC, QDisc);
+4 -4
View File
@@ -45,7 +45,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
}
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(tclass_freep) TClass *tclass = NULL;
TrafficControl *existing;
int r;
@@ -55,7 +55,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
assert(filename);
assert(section_line > 0);
r = network_config_section_new(filename, section_line, &n);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
@@ -82,7 +82,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
tclass->network = network;
tclass->section = TAKE_PTR(n);
r = ordered_hashmap_ensure_put(&network->tc_by_section, &network_config_hash_ops, tclass->section, tclass);
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, tclass->section, tclass);
if (r < 0)
return r;
@@ -97,7 +97,7 @@ TClass* tclass_free(TClass *tclass) {
if (tclass->network && tclass->section)
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
network_config_section_free(tclass->section);
config_section_free(tclass->section);
return mfree(tclass);
}
+2 -2
View File
@@ -19,7 +19,7 @@ typedef enum TClassKind {
typedef struct TClass {
TrafficControl meta;
NetworkConfigSection *section;
ConfigSection *section;
Network *network;
uint32_t classid;
@@ -59,7 +59,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
int tclass_configure(Link *link, TClass *tclass);
int tclass_section_verify(TClass *tclass);
DEFINE_NETWORK_SECTION_FUNCTIONS(TClass, tclass_free);
DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free);
DEFINE_TC_CAST(TCLASS, TClass);
+44
View File
@@ -573,6 +573,50 @@ int config_parse_many(
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
}
static void config_section_hash_func(const ConfigSection *c, struct siphash *state) {
siphash24_compress_string(c->filename, state);
siphash24_compress(&c->line, sizeof(c->line), state);
}
static int config_section_compare_func(const ConfigSection *x, const ConfigSection *y) {
int r;
r = strcmp(x->filename, y->filename);
if (r != 0)
return r;
return CMP(x->line, y->line);
}
DEFINE_HASH_OPS(config_section_hash_ops, ConfigSection, config_section_hash_func, config_section_compare_func);
int config_section_new(const char *filename, unsigned line, ConfigSection **s) {
ConfigSection *cs;
cs = malloc0(offsetof(ConfigSection, filename) + strlen(filename) + 1);
if (!cs)
return -ENOMEM;
strcpy(cs->filename, filename);
cs->line = line;
*s = TAKE_PTR(cs);
return 0;
}
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
ConfigSection *cs;
unsigned n = 0;
void *entry;
HASHMAP_FOREACH_KEY(entry, cs, hashmap)
if (n < cs->line)
n = cs->line;
return n + 1;
}
#define DEFINE_PARSER(type, vartype, conv_func) \
DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
+37
View File
@@ -114,6 +114,43 @@ int config_parse_many(
void *userdata,
Hashmap **ret_stats_by_path); /* possibly NULL */
typedef struct ConfigSection {
unsigned line;
bool invalid;
char filename[];
} ConfigSection;
static inline ConfigSection* config_section_free(ConfigSection *cs) {
return mfree(cs);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(ConfigSection*, config_section_free);
int config_section_new(const char *filename, unsigned line, ConfigSection **s);
extern const struct hash_ops config_section_hash_ops;
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
static inline bool section_is_invalid(ConfigSection *section) {
/* If this returns false, then it does _not_ mean the section is valid. */
if (!section)
return false;
return section->invalid;
}
#define DEFINE_SECTION_CLEANUP_FUNCTIONS(type, free_func) \
static inline type* free_func##_or_set_invalid(type *p) { \
assert(p); \
\
if (p->section) \
p->section->invalid = true; \
else \
free_func(p); \
return NULL; \
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
CONFIG_PARSER_PROTOTYPE(config_parse_int);
CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
CONFIG_PARSER_PROTOTYPE(config_parse_long);
+2
View File
@@ -224,6 +224,8 @@ shared_sources = files('''
net-condition.h
netif-naming-scheme.c
netif-naming-scheme.h
netif-sriov.c
netif-sriov.h
netif-util.c
netif-util.h
nscd-flush.h
+631
View File
@@ -0,0 +1,631 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "device-util.h"
#include "netlink-util.h"
#include "netif-sriov.h"
#include "parse-util.h"
#include "set.h"
#include "stdio-util.h"
#include "string-util.h"
static int sr_iov_new(SRIOV **ret) {
SRIOV *sr_iov;
assert(ret);
sr_iov = new(SRIOV, 1);
if (!sr_iov)
return -ENOMEM;
*sr_iov = (SRIOV) {
.vf = UINT32_MAX,
.vlan_proto = ETH_P_8021Q,
.vf_spoof_check_setting = -1,
.trust = -1,
.query_rss = -1,
.link_state = _SR_IOV_LINK_STATE_INVALID,
};
*ret = TAKE_PTR(sr_iov);
return 0;
}
static int sr_iov_new_static(OrderedHashmap **sr_iov_by_section, const char *filename, unsigned section_line, SRIOV **ret) {
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(sr_iov_freep) SRIOV *sr_iov = NULL;
SRIOV *existing = NULL;
int r;
assert(sr_iov_by_section);
assert(filename);
assert(section_line > 0);
assert(ret);
r = config_section_new(filename, section_line, &n);
if (r < 0)
return r;
existing = ordered_hashmap_get(*sr_iov_by_section, n);
if (existing) {
*ret = existing;
return 0;
}
r = sr_iov_new(&sr_iov);
if (r < 0)
return r;
r = ordered_hashmap_ensure_put(sr_iov_by_section, &config_section_hash_ops, n, sr_iov);
if (r < 0)
return r;
sr_iov->section = TAKE_PTR(n);
sr_iov->sr_iov_by_section = *sr_iov_by_section;
*ret = TAKE_PTR(sr_iov);
return 0;
}
SRIOV *sr_iov_free(SRIOV *sr_iov) {
if (!sr_iov)
return NULL;
if (sr_iov->sr_iov_by_section && sr_iov->section)
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
config_section_free(sr_iov->section);
return mfree(sr_iov);
}
int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req) {
int r;
assert(sr_iov);
assert(req);
r = sd_netlink_message_open_container(req, IFLA_VFINFO_LIST);
if (r < 0)
return r;
r = sd_netlink_message_open_container(req, IFLA_VF_INFO);
if (r < 0)
return r;
if (!ether_addr_is_null(&sr_iov->mac)) {
struct ifla_vf_mac ivm = {
.vf = sr_iov->vf,
};
memcpy(ivm.mac, &sr_iov->mac, ETH_ALEN);
r = sd_netlink_message_append_data(req, IFLA_VF_MAC, &ivm, sizeof(struct ifla_vf_mac));
if (r < 0)
return r;
}
if (sr_iov->vf_spoof_check_setting >= 0) {
struct ifla_vf_spoofchk ivs = {
.vf = sr_iov->vf,
.setting = sr_iov->vf_spoof_check_setting,
};
r = sd_netlink_message_append_data(req, IFLA_VF_SPOOFCHK, &ivs, sizeof(struct ifla_vf_spoofchk));
if (r < 0)
return r;
}
if (sr_iov->query_rss >= 0) {
struct ifla_vf_rss_query_en ivs = {
.vf = sr_iov->vf,
.setting = sr_iov->query_rss,
};
r = sd_netlink_message_append_data(req, IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(struct ifla_vf_rss_query_en));
if (r < 0)
return r;
}
if (sr_iov->trust >= 0) {
struct ifla_vf_trust ivt = {
.vf = sr_iov->vf,
.setting = sr_iov->trust,
};
r = sd_netlink_message_append_data(req, IFLA_VF_TRUST, &ivt, sizeof(struct ifla_vf_trust));
if (r < 0)
return r;
}
if (sr_iov->link_state >= 0) {
struct ifla_vf_link_state ivl = {
.vf = sr_iov->vf,
.link_state = sr_iov->link_state,
};
r = sd_netlink_message_append_data(req, IFLA_VF_LINK_STATE, &ivl, sizeof(struct ifla_vf_link_state));
if (r < 0)
return r;
}
if (sr_iov->vlan > 0) {
/* Because of padding, first the buffer must be initialized with 0. */
struct ifla_vf_vlan_info ivvi = {};
ivvi.vf = sr_iov->vf;
ivvi.vlan = sr_iov->vlan;
ivvi.qos = sr_iov->qos;
ivvi.vlan_proto = htobe16(sr_iov->vlan_proto);
r = sd_netlink_message_open_container(req, IFLA_VF_VLAN_LIST);
if (r < 0)
return r;
r = sd_netlink_message_append_data(req, IFLA_VF_VLAN_INFO, &ivvi, sizeof(struct ifla_vf_vlan_info));
if (r < 0)
return r;
r = sd_netlink_message_close_container(req);
if (r < 0)
return r;
}
r = sd_netlink_message_close_container(req);
if (r < 0)
return r;
r = sd_netlink_message_close_container(req);
if (r < 0)
return r;
return 0;
}
int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret) {
const char *str;
uint32_t n;
int r;
assert(device);
assert(ret);
r = sd_device_get_sysattr_value(device, "device/sriov_numvfs", &str);
if (r < 0)
return r;
r = safe_atou32(str, &n);
if (r < 0)
return r;
*ret = n;
return 0;
}
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) {
char val[DECIMAL_STR_MAX(uint32_t)];
const char *str;
int r;
assert(device);
if (num_vfs == UINT32_MAX) {
uint32_t current_num_vfs;
SRIOV *sr_iov;
/* If the number of virtual functions is not specified, then use the maximum number of VF + 1. */
num_vfs = 0;
ORDERED_HASHMAP_FOREACH(sr_iov, sr_iov_by_section)
num_vfs = MAX(num_vfs, sr_iov->vf + 1);
if (num_vfs == 0) /* No VF is configured. */
return 0;
r = sr_iov_get_num_vfs(device, &current_num_vfs);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to get the current number of SR-IOV virtual functions: %m");
/* Enough VFs already exist. */
if (num_vfs <= current_num_vfs)
return 0;
} else if (num_vfs == 0) {
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", "0");
if (r < 0)
log_device_debug_errno(device, r, "Failed to write device/sriov_numvfs sysfs attribute, ignoring: %m");
/* Gracefully handle the error in disabling VFs when the interface does not support SR-IOV. */
return r == -ENOENT ? 0 : r;
}
/* So, the interface does not have enough VFs. Before increasing the number of VFs, check the
* maximum allowed number of VFs from the sriov_totalvfs sysattr. Note that the sysattr
* currently exists only for PCI drivers. Hence, ignore -ENOENT.
* TODO: netdevsim provides the information in debugfs. */
r = sd_device_get_sysattr_value(device, "device/sriov_totalvfs", &str);
if (r >= 0) {
uint32_t max_num_vfs;
r = safe_atou32(str, &max_num_vfs);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse device/sriov_totalvfs sysfs attribute '%s': %m", str);
if (num_vfs > max_num_vfs)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ERANGE),
"Specified number of virtual functions is out of range. "
"The maximum allowed value is %"PRIu32".",
max_num_vfs);
} else if (r != -ENOENT) /* Currently, only PCI driver has the attribute. */
return log_device_debug_errno(device, r, "Failed to read device/sriov_totalvfs sysfs attribute: %m");
xsprintf(val, "%"PRIu32, num_vfs);
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", val);
if (r == -EBUSY) {
/* Some devices e.g. netdevsim refuse to set sriov_numvfs if it has non-zero value. */
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", "0");
if (r >= 0)
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", val);
}
if (r < 0)
return log_device_debug_errno(device, r, "Failed to write device/sriov_numvfs sysfs attribute: %m");
log_device_debug(device, "device/sriov_numvfs sysfs attribute set to '%s'.", val);
return 0;
}
static int sr_iov_section_verify(uint32_t num_vfs, SRIOV *sr_iov) {
assert(sr_iov);
if (section_is_invalid(sr_iov->section))
return -EINVAL;
if (sr_iov->vf == UINT32_MAX)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: [SR-IOV] section without VirtualFunction= field configured. "
"Ignoring [SR-IOV] section from line %u.",
sr_iov->section->filename, sr_iov->section->line);
if (sr_iov->vf >= num_vfs)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: VirtualFunction= must be smaller than the value specified in SR-IOVVirtualFunctions=. "
"Ignoring [SR-IOV] section from line %u.",
sr_iov->section->filename, sr_iov->section->line);
return 0;
}
int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) {
_cleanup_hashmap_free_ Hashmap *hashmap = NULL;
SRIOV *sr_iov;
int r;
ORDERED_HASHMAP_FOREACH(sr_iov, sr_iov_by_section) {
SRIOV *dup;
if (sr_iov_section_verify(num_vfs, sr_iov) < 0) {
sr_iov_free(sr_iov);
continue;
}
assert(sr_iov->vf < INT_MAX);
dup = hashmap_remove(hashmap, UINT32_TO_PTR(sr_iov->vf + 1));
if (dup) {
log_warning("%s: Conflicting [SR-IOV] section is specified at line %u and %u, "
"dropping the [SR-IOV] section specified at line %u.",
dup->section->filename, sr_iov->section->line,
dup->section->line, dup->section->line);
sr_iov_free(dup);
}
r = hashmap_ensure_put(&hashmap, NULL, UINT32_TO_PTR(sr_iov->vf + 1), sr_iov);
if (r < 0)
return log_oom();
assert(r > 0);
}
return 0;
}
int config_parse_sr_iov_uint32(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
OrderedHashmap **sr_iov_by_section = data;
uint32_t k;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
if (streq(lvalue, "VirtualFunction"))
sr_iov->vf = UINT32_MAX;
else if (streq(lvalue, "VLANId"))
sr_iov->vlan = 0;
else if (streq(lvalue, "QualityOfService"))
sr_iov->qos = 0;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "VLANId")) {
if (k == 0 || k > 4095) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV VLANId: %d", k);
return 0;
}
sr_iov->vlan = k;
} else if (streq(lvalue, "VirtualFunction")) {
if (k >= INT_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV virtual function: %d", k);
return 0;
}
sr_iov->vf = k;
} else if (streq(lvalue, "QualityOfService"))
sr_iov->qos = k;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_vlan_proto(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
OrderedHashmap **sr_iov_by_section = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue) || streq(rvalue, "802.1Q"))
sr_iov->vlan_proto = ETH_P_8021Q;
else if (streq(rvalue, "802.1ad"))
sr_iov->vlan_proto = ETH_P_8021AD;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_link_state(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
OrderedHashmap **sr_iov_by_section = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
if (r < 0)
return r;
/* Unfortunately, SR_IOV_LINK_STATE_DISABLE is 2, not 0. So, we cannot use
* DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN() macro. */
if (isempty(rvalue)) {
sr_iov->link_state = _SR_IOV_LINK_STATE_INVALID;
TAKE_PTR(sr_iov);
return 0;
}
if (streq(rvalue, "auto")) {
sr_iov->link_state = SR_IOV_LINK_STATE_AUTO;
TAKE_PTR(sr_iov);
return 0;
}
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
sr_iov->link_state = r ? SR_IOV_LINK_STATE_ENABLE : SR_IOV_LINK_STATE_DISABLE;
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_boolean(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
OrderedHashmap **sr_iov_by_section = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
if (streq(lvalue, "MACSpoofCheck"))
sr_iov->vf_spoof_check_setting = -1;
else if (streq(lvalue, "QueryReceiveSideScaling"))
sr_iov->query_rss = -1;
else if (streq(lvalue, "Trust"))
sr_iov->trust = -1;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse '%s=', ignoring: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "MACSpoofCheck"))
sr_iov->vf_spoof_check_setting = r;
else if (streq(lvalue, "QueryReceiveSideScaling"))
sr_iov->query_rss = r;
else if (streq(lvalue, "Trust"))
sr_iov->trust = r;
else
assert_not_reached();
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_mac(
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
OrderedHashmap **sr_iov_by_section = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
if (r < 0)
return r;
if (isempty(rvalue)) {
sr_iov->mac = ETHER_ADDR_NULL;
TAKE_PTR(sr_iov);
return 0;
}
r = parse_ether_addr(rvalue, &sr_iov->mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
return 0;
}
TAKE_PTR(sr_iov);
return 0;
}
int config_parse_sr_iov_num_vfs(
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) {
uint32_t n, *num_vfs = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*num_vfs = UINT32_MAX;
return 0;
}
r = safe_atou32(rvalue, &n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (n > INT_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"The number of SR-IOV virtual functions is too large. It must be equal to "
"or smaller than 2147483647. Ignoring assignment: %"PRIu32, n);
return 0;
}
*num_vfs = n;
return 0;
}
+48
View File
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <linux/if_link.h>
#include "sd-device.h"
#include "conf-parser.h"
#include "ether-addr-util.h"
#include "hashmap.h"
typedef enum SRIOVLinkState {
SR_IOV_LINK_STATE_AUTO = IFLA_VF_LINK_STATE_AUTO,
SR_IOV_LINK_STATE_ENABLE = IFLA_VF_LINK_STATE_ENABLE,
SR_IOV_LINK_STATE_DISABLE = IFLA_VF_LINK_STATE_DISABLE,
_SR_IOV_LINK_STATE_MAX,
_SR_IOV_LINK_STATE_INVALID = -EINVAL,
} SRIOVLinkState;
typedef struct SRIOV {
ConfigSection *section;
OrderedHashmap *sr_iov_by_section;
uint32_t vf; /* 0 - 2147483646 */
uint32_t vlan; /* 0 - 4095, 0 disables VLAN filter */
uint32_t qos;
uint16_t vlan_proto; /* ETH_P_8021Q or ETH_P_8021AD */
int vf_spoof_check_setting;
int query_rss;
int trust;
SRIOVLinkState link_state;
struct ether_addr mac;
} SRIOV;
SRIOV *sr_iov_free(SRIOV *sr_iov);
int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req);
int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret);
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_free);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_uint32);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_link_state);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_vlan_proto);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_mac);
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_num_vfs);
+11
View File
@@ -8,6 +8,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "ethtool-util.h"
#include "link-config.h"
#include "net-condition.h"
#include "netif-sriov.h"
#include "socket-util.h"
%}
struct ConfigPerfItem;
@@ -101,3 +102,13 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32,
Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)
Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)
Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval)
Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs)
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, offsetof(LinkConfig, sr_iov_by_section)
+86 -1
View File
@@ -22,6 +22,7 @@
#include "log-link.h"
#include "memory-util.h"
#include "net-condition.h"
#include "netif-sriov.h"
#include "netif-util.h"
#include "netlink-util.h"
#include "parse-util.h"
@@ -60,6 +61,8 @@ static LinkConfig* link_config_free(LinkConfig *config) {
free(config->wol_password_file);
erase_and_free(config->wol_password);
ordered_hashmap_free_with_destructor(config->sr_iov_by_section, sr_iov_free);
return mfree(config);
}
@@ -247,6 +250,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
.txqueuelen = UINT32_MAX,
.coalesce.use_adaptive_rx_coalesce = -1,
.coalesce.use_adaptive_tx_coalesce = -1,
.sr_iov_num_vfs = UINT32_MAX,
};
for (i = 0; i < ELEMENTSOF(config->features); i++)
@@ -257,7 +261,9 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
STRV_MAKE_CONST(filename),
(const char* const*) CONF_PATHS_STRV("systemd/network"),
dropin_dirname,
"Match\0Link\0",
"Match\0"
"Link\0"
"SR-IOV\0",
config_item_perf_lookup, link_config_gperf_lookup,
CONFIG_PARSE_WARN, config, NULL);
if (r < 0)
@@ -285,6 +291,10 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
if (r < 0)
return r;
r = sr_iov_drop_invalid_sections(config->sr_iov_num_vfs, config->sr_iov_by_section);
if (r < 0)
return r;
log_debug("Parsed configuration file %s", filename);
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
@@ -830,6 +840,77 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
return 0;
}
static int sr_iov_configure(Link *link, sd_netlink **rtnl, SRIOV *sr_iov) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(rtnl);
assert(link->ifindex > 0);
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
r = sd_rtnl_message_new_link(*rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return r;
r = sr_iov_set_netlink_message(sr_iov, req);
if (r < 0)
return r;
r = sd_netlink_call(*rtnl, req, 0, NULL);
if (r < 0)
return r;
return 0;
}
static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
SRIOV *sr_iov;
uint32_t n;
int r;
assert(link);
assert(link->config);
assert(link->device);
r = sr_iov_set_num_vfs(link->device, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
if (r < 0)
log_link_warning_errno(link, r, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
if (ordered_hashmap_isempty(link->config->sr_iov_by_section))
return 0;
r = sr_iov_get_num_vfs(link->device, &n);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to get the number of SR-IOV virtual functions, ignoring [SR-IOV] sections: %m");
return 0;
}
if (n == 0) {
log_link_warning(link, "No SR-IOV virtual function exists, ignoring [SR-IOV] sections: %m");
return 0;
}
ORDERED_HASHMAP_FOREACH(sr_iov, link->config->sr_iov_by_section) {
if (sr_iov->vf >= n) {
log_link_warning(link, "SR-IOV virtual function %"PRIu32" does not exist, ignoring.", sr_iov->vf);
continue;
}
r = sr_iov_configure(link, rtnl, sr_iov);
if (r < 0)
log_link_warning_errno(link, r,
"Failed to configure SR-IOV virtual function %"PRIu32", ignoring: %m",
sr_iov->vf);
}
return 0;
}
int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
int r;
@@ -861,6 +942,10 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
if (r < 0)
return r;
r = link_apply_sr_iov_config(link, rtnl);
if (r < 0)
return r;
return 0;
}
+4
View File
@@ -7,6 +7,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "ethtool-util.h"
#include "hashmap.h"
#include "list.h"
#include "net-condition.h"
#include "netif-naming-scheme.h"
@@ -76,6 +77,9 @@ struct LinkConfig {
int autoneg_flow_control;
netdev_coalesce_param coalesce;
uint32_t sr_iov_num_vfs;
OrderedHashmap *sr_iov_by_section;
LIST_FIELDS(LinkConfig, configs);
};