Skip to content

Commit 4902e90

Browse files
Added networkd backend
Signed-off-by: Patryk Strusiewicz-Surmacki <[email protected]>
1 parent 0e96bd3 commit 4902e90

File tree

8 files changed

+247
-42
lines changed

8 files changed

+247
-42
lines changed

doc/netplan-yaml.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,11 @@ The specific settings for bridges are defined below.
13611361
- **`vlan-filtering`** (boolean)
13621362

13631363
> Enables VLAN filtering. Will be enabled by default if *vlans* are defined.
1364+
1365+
- **`vlan-default-pvid`** (scalar)
1366+
1367+
> Specifies the default port VLAN ID. Can be set to values between 1 and 4094,
1368+
> or to value `none` if `networkd` is used as a renderer. Defaults to `1`.
13641369

13651370
- **`hello-time`** (scalar)
13661371

src/abi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ struct netplan_net_definition {
345345
GArray* vlans;
346346
GArray* port_vlans;
347347
gboolean vlan_filtering;
348+
char* vlan_default_pvid;
348349
} bridge_params;
349350
gboolean custom_bridging;
350351

@@ -438,7 +439,7 @@ struct netplan_net_definition {
438439

439440
typedef struct {
440441
guint vid; //[1..4094]
441-
guint vid_to; //set iff vid range defined
442+
guint vid_to; //set if vid range is defined
442443
gboolean pvid;
443444
gboolean untagged;
444445
} NetplanBridgeVlan;

src/netplan.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,9 @@ write_bridge_params(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanN
356356
}
357357
}
358358

359-
359+
if (def->bridge_params.vlan_default_pvid) {
360+
YAML_STRING(def, event, emitter, "vlan-default-pvid", def->bridge_params.vlan_default_pvid);
361+
}
360362

361363
YAML_MAPPING_CLOSE(event, emitter);
362364
}

src/networkd.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,10 @@ write_bridge_params_networkd(GString* s, const NetplanNetDefinition* def)
215215
if (def->bridge_params.max_age)
216216
g_string_append_printf(params, "MaxAgeSec=%s\n", def->bridge_params.max_age);
217217
g_string_append_printf(params, "STP=%s\n", def->bridge_params.stp ? "true" : "false");
218-
if (def->bridge_params.vlans) {
219-
// TODO: research and implement bridge vlans for networkd
220-
g_fprintf(stderr, "ERROR: %s: networkd does not support bridge vlans\n", def->id);
221-
exit(1);
222-
}
218+
if (def->bridge_params.vlan_default_pvid)
219+
g_string_append_printf(params, "DefaultPVID=%s\n", def->bridge_params.vlan_default_pvid);
220+
if(def->bridge_params.vlan_filtering || def->bridge_params.vlans)
221+
g_string_append_printf(params, "VLANFiltering=true\n");
223222

224223
g_string_append_printf(s, "\n[Bridge]\n%s", params->str);
225224

@@ -836,6 +835,47 @@ combine_dhcp_overrides(const NetplanNetDefinition* def, NetplanDHCPOverrides* co
836835
return TRUE;
837836
}
838837

838+
/**
839+
* Return networkd vlan string.
840+
*/
841+
GString*
842+
bridge_vlan_networkd_str(const NetplanBridgeVlan* vlan)
843+
{
844+
GString *id = g_string_sized_new(9);
845+
GString *def = g_string_sized_new(200);
846+
847+
g_string_append_printf(id, "%u", vlan->vid);
848+
if (vlan->vid_to)
849+
g_string_append_printf(id, "-%u", vlan->vid_to);
850+
851+
852+
if (vlan->pvid)
853+
g_string_append_printf(def, "PVID=%s\n", id->str);
854+
else {
855+
g_string_append_printf(def, "VLAN=%s\n", id->str);
856+
}
857+
858+
if (vlan->untagged)
859+
g_string_append_printf(def, "EgressUntagged=%s\n", id->str);
860+
861+
g_string_free(id, TRUE);
862+
863+
return def;
864+
}
865+
866+
/**
867+
* Write the needed networkd .network BridgeVLAN configuration for the selected vlan definition.
868+
*/
869+
STATIC void
870+
write_vlans(GString_autoptr network, GArray* data) {
871+
g_string_append(network, "\n[BridgeVLAN]\n");
872+
for (unsigned i = 0; i < data->len; ++i) {
873+
GString* v = bridge_vlan_networkd_str(g_array_index(data,NetplanBridgeVlan*, i));
874+
g_string_append_printf(network, "%s", v->str);
875+
g_string_free(v, TRUE);
876+
}
877+
}
878+
839879
/**
840880
* Write the needed networkd .network configuration for the selected netplan definition.
841881
*/
@@ -988,11 +1028,16 @@ _netplan_netdef_write_network_file(
9881028
if (def->bridge_neigh_suppress != NETPLAN_TRISTATE_UNSET)
9891029
g_string_append_printf(network, "NeighborSuppression=%s\n", def->bridge_neigh_suppress ? "true" : "false");
9901030
if (def->bridge_params.port_vlans) {
991-
// TODO: research and implement bridge port-vlans for networkd
992-
g_fprintf(stderr, "ERROR: %s: networkd does not support bridge port-vlans\n", def->id);
993-
exit(1);
1031+
// port's .netowrk file
1032+
write_vlans(network, def->bridge_params.port_vlans);
9941033
}
9951034
}
1035+
1036+
if (!def->bridge && !def->bond && def->backend != NETPLAN_BACKEND_OVS && def->bridge_params.vlans) {
1037+
// bridge's .network file
1038+
write_vlans(network, def->bridge_params.vlans);
1039+
}
1040+
9961041
if (def->bond && def->backend != NETPLAN_BACKEND_OVS) {
9971042
g_string_append_printf(network, "Bond=%s\n", def->bond);
9981043

src/nm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,13 @@ write_bridge_params_nm(const NetplanNetDefinition* def, GKeyFile *kf)
412412
g_key_file_set_boolean(kf, "bridge", "stp", def->bridge_params.stp);
413413
if(def->bridge_params.vlan_filtering || def->bridge_params.vlans)
414414
g_key_file_set_string(kf, "bridge", "vlan-filtering", "true");
415+
if (def->bridge_params.vlan_default_pvid) {
416+
if (g_str_equal(def->bridge_params.vlan_default_pvid, "none")) {
417+
g_fprintf(stderr, "ERROR: vlan-default-pvid cannot be set to 'none' if NetworkManager is used\n");
418+
exit(1);
419+
}
420+
g_key_file_set_string(kf, "bridge", "vlan-default-pvid", def->bridge_params.vlan_default_pvid);
421+
}
415422
if (def->bridge_params.vlans) {
416423
for (unsigned i = 0; i < def->bridge_params.vlans->len; ++i) {
417424
if (i > 0)

src/parse.c

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,7 @@ handle_generic_vlans(NetplanParser* npp, yaml_node_t* node, GArray** entryptr, G
21782178
re_inited = TRUE;
21792179
}
21802180

2181+
unsigned pvids = 0;
21812182
for (yaml_node_item_t *i = node->data.sequence.items.start; i < node->data.sequence.items.top; i++) {
21822183
g_autofree char* vlan = NULL;
21832184
yaml_node_t *entry = yaml_document_get_node(&npp->doc, *i);
@@ -2187,6 +2188,9 @@ handle_generic_vlans(NetplanParser* npp, yaml_node_t* node, GArray** entryptr, G
21872188

21882189
size_t maxGroups = 7+1;
21892190
regmatch_t groups[maxGroups];
2191+
2192+
guint minVid = npp->global_backend == NETPLAN_BACKEND_NETWORKD ? 0:1;
2193+
21902194
/* does it match the vlans= definition? */
21912195
if (regexec(&re, vlan, maxGroups, groups, 0) == 0) {
21922196
NetplanBridgeVlan* data = g_new0(NetplanBridgeVlan, 1);
@@ -2201,27 +2205,50 @@ handle_generic_vlans(NetplanParser* npp, yaml_node_t* node, GArray** entryptr, G
22012205
switch (g) {
22022206
case 1:
22032207
v = (guint) g_ascii_strtoull(cursorCopy + groups[g].rm_so, NULL, 10);
2204-
if (v < 1 || v > 4094)
2205-
return yaml_error(npp, node, error, "malformed vlan vid '%u', must be in range [1..4094]", v);
2208+
if (v < minVid || v > 4094) {
2209+
g_free(data);
2210+
return yaml_error(npp, node, error, "malformed vlan vid '%u', must be in range [%d..4094]", v, minVid);
2211+
}
22062212
data->vid = v;
22072213
break;
22082214
case 3:
22092215
v = (guint) g_ascii_strtoull(cursorCopy + groups[g].rm_so, NULL, 10);
2210-
if (v < 1 || v > 4094)
2216+
if (v < 1 || v > 4094) {
2217+
g_free(data);
22112218
return yaml_error(npp, node, error, "malformed vlan vid '%u', must be in range [1..4094]", v);
2212-
else if (v <= data->vid)
2213-
return yaml_error(npp, node, error, "malformed vlan vid range '%s': %u > %u!", scalar(entry), data->vid, v);
2219+
}
2220+
2221+
else if (v <= data->vid) {
2222+
guint vid = data->vid;
2223+
g_free(data);
2224+
return yaml_error(npp, node, error, "malformed vlan vid range '%s': %u > %u!", scalar(entry), vid, v);
2225+
}
2226+
22142227
data->vid_to = v;
22152228
break;
22162229
case 5:
22172230
data->pvid = TRUE;
2231+
if (++pvids > 1) {
2232+
g_free(data);
2233+
return yaml_error(npp, node, error, "malformed vlan pvid '%s': only single pvid can be defined", scalar(entry));
2234+
}
22182235
break;
22192236
case 7:
22202237
data->untagged = TRUE;
22212238
break;
22222239
default: g_assert_not_reached(); // LCOV_EXCL_LINE
22232240
}
22242241
}
2242+
2243+
if (npp->global_backend == NETPLAN_BACKEND_NETWORKD && !data->pvid && data->vid == 0) {
2244+
g_free(data);
2245+
return yaml_error(npp, node, error, "malformed vlan '%s': value cannot be defined as 0 for non-pvid", scalar(entry));
2246+
}
2247+
2248+
if (data->vid_to > 0 && data->pvid) {
2249+
g_free(data);
2250+
return yaml_error(npp, node, error, "malformed vlan '%s': pvid cannot be defined as a range", scalar(entry));
2251+
}
22252252
if (!*entryptr)
22262253
*entryptr = g_array_new(FALSE, FALSE, sizeof(NetplanBridgeVlan*));
22272254
g_array_append_val(*entryptr, data);
@@ -2269,6 +2296,24 @@ handle_bridge_port_vlans(NetplanParser* npp, yaml_node_t* node, const char*, con
22692296
return TRUE;
22702297
}
22712298

2299+
/**
2300+
* Handler for vlan-default-pvid.
2301+
* @data: offset into NetplanNetDefinition where the const char* field to write is
2302+
* located
2303+
*/
2304+
STATIC gboolean
2305+
handle_vlan_default_pvid(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
2306+
{
2307+
const char* pvid = scalar(node);
2308+
GError** err = NULL;
2309+
guint64 val = 0;
2310+
if (strcmp(pvid, "none") != 0 && !g_ascii_string_to_unsigned(pvid, 10, 1, 4094 , &val, err)) {
2311+
return yaml_error(npp, node, error, "malformed value of vlan-default-pvid '%s': vlan-default-pvid can only be defined as a single port ID", pvid);
2312+
}
2313+
2314+
return handle_netdef_str(npp, node, data, error);
2315+
}
2316+
22722317
static const mapping_entry_handler bridge_params_handlers[] = {
22732318
{"ageing-time", YAML_SCALAR_NODE, {.generic=handle_netdef_str}, netdef_offset(bridge_params.ageing_time)},
22742319
{"aging-time", YAML_SCALAR_NODE, {.generic=handle_netdef_str}, netdef_offset(bridge_params.ageing_time)},
@@ -2282,6 +2327,7 @@ static const mapping_entry_handler bridge_params_handlers[] = {
22822327
{"port-vlans", YAML_MAPPING_NODE, {.map={.custom=handle_bridge_port_vlans}}, netdef_offset(bridge_params.port_vlans)},
22832328
{"vlans", YAML_SEQUENCE_NODE, {.generic=handle_bridge_vlans}, netdef_offset(bridge_params.vlans)},
22842329
{"vlan-filtering", YAML_SCALAR_NODE, {.generic=handle_netdef_bool}, netdef_offset(bridge_params.vlan_filtering)},
2330+
{"vlan-default-pvid", YAML_SCALAR_NODE, {.generic=handle_vlan_default_pvid}, netdef_offset(bridge_params.vlan_default_pvid)},
22852331
{NULL}
22862332
};
22872333

src/types.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ reset_netdef(NetplanNetDefinition* netdef, NetplanDefType new_type, NetplanBacke
342342
free_garray_with_destructor(&netdef->bridge_params.vlans, g_free);
343343
free_garray_with_destructor(&netdef->bridge_params.port_vlans, g_free);
344344
netdef->bridge_params.vlan_filtering = FALSE;
345+
FREE_AND_NULLIFY(netdef->bridge_params.vlan_default_pvid);
345346
memset(&netdef->bridge_params, 0, sizeof(netdef->bridge_params));
346347
netdef->custom_bridging = FALSE;
347348

0 commit comments

Comments
 (0)