Skip to content

Commit 6407125

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

File tree

8 files changed

+211
-40
lines changed

8 files changed

+211
-40
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: 1 addition & 0 deletions
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

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: 42 additions & 4 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,7 @@ 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+
21902192
/* does it match the vlans= definition? */
21912193
if (regexec(&re, vlan, maxGroups, groups, 0) == 0) {
21922194
NetplanBridgeVlan* data = g_new0(NetplanBridgeVlan, 1);
@@ -2201,27 +2203,44 @@ handle_generic_vlans(NetplanParser* npp, yaml_node_t* node, GArray** entryptr, G
22012203
switch (g) {
22022204
case 1:
22032205
v = (guint) g_ascii_strtoull(cursorCopy + groups[g].rm_so, NULL, 10);
2204-
if (v < 1 || v > 4094)
2206+
if (v < 1 || v > 4094) {
2207+
g_free(data);
22052208
return yaml_error(npp, node, error, "malformed vlan vid '%u', must be in range [1..4094]", v);
2209+
}
22062210
data->vid = v;
22072211
break;
22082212
case 3:
22092213
v = (guint) g_ascii_strtoull(cursorCopy + groups[g].rm_so, NULL, 10);
2210-
if (v < 1 || v > 4094)
2214+
if (v < 1 || v > 4094) {
2215+
g_free(data);
22112216
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);
2217+
}
2218+
2219+
else if (v <= data->vid) {
2220+
guint vid = data->vid;
2221+
g_free(data);
2222+
return yaml_error(npp, node, error, "malformed vlan vid range '%s': %u > %u!", scalar(entry), vid, v);
2223+
}
2224+
22142225
data->vid_to = v;
22152226
break;
22162227
case 5:
22172228
data->pvid = TRUE;
2229+
if (++pvids > 1) {
2230+
g_free(data);
2231+
return yaml_error(npp, node, error, "malformed vlan pvid '%s': only single pvid can be defined", scalar(entry));
2232+
}
22182233
break;
22192234
case 7:
22202235
data->untagged = TRUE;
22212236
break;
22222237
default: g_assert_not_reached(); // LCOV_EXCL_LINE
22232238
}
22242239
}
2240+
if (data->vid_to > 0 && data->pvid) {
2241+
g_free(data);
2242+
return yaml_error(npp, node, error, "malformed vlan '%s': pvid cannot be defined as a range", scalar(entry));
2243+
}
22252244
if (!*entryptr)
22262245
*entryptr = g_array_new(FALSE, FALSE, sizeof(NetplanBridgeVlan*));
22272246
g_array_append_val(*entryptr, data);
@@ -2269,6 +2288,24 @@ handle_bridge_port_vlans(NetplanParser* npp, yaml_node_t* node, const char*, con
22692288
return TRUE;
22702289
}
22712290

2291+
/**
2292+
* Handler for vlan-default-pvid.
2293+
* @data: offset into NetplanNetDefinition where the const char* field to write is
2294+
* located
2295+
*/
2296+
STATIC gboolean
2297+
handle_vlan_default_pvid(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
2298+
{
2299+
const char* pvid = scalar(node);
2300+
GError** err = NULL;
2301+
guint64 val = 0;
2302+
if (strcmp(pvid, "none") != 0 && !g_ascii_string_to_unsigned(pvid, 10, 1, 4094 , &val, err)) {
2303+
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);
2304+
}
2305+
2306+
return handle_netdef_str(npp, node, data, error);
2307+
}
2308+
22722309
static const mapping_entry_handler bridge_params_handlers[] = {
22732310
{"ageing-time", YAML_SCALAR_NODE, {.generic=handle_netdef_str}, netdef_offset(bridge_params.ageing_time)},
22742311
{"aging-time", YAML_SCALAR_NODE, {.generic=handle_netdef_str}, netdef_offset(bridge_params.ageing_time)},
@@ -2282,6 +2319,7 @@ static const mapping_entry_handler bridge_params_handlers[] = {
22822319
{"port-vlans", YAML_MAPPING_NODE, {.map={.custom=handle_bridge_port_vlans}}, netdef_offset(bridge_params.port_vlans)},
22832320
{"vlans", YAML_SEQUENCE_NODE, {.generic=handle_bridge_vlans}, netdef_offset(bridge_params.vlans)},
22842321
{"vlan-filtering", YAML_SCALAR_NODE, {.generic=handle_netdef_bool}, netdef_offset(bridge_params.vlan_filtering)},
2322+
{"vlan-default-pvid", YAML_SCALAR_NODE, {.generic=handle_vlan_default_pvid}, netdef_offset(bridge_params.vlan_default_pvid)},
22852323
{NULL}
22862324
};
22872325

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)