schema: add toplevel ethernet node

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2021-08-03 09:59:46 +02:00
parent efee6698cf
commit 50ab44b0f5
7 changed files with 205 additions and 8 deletions

View File

@@ -207,14 +207,7 @@ let wiphy = {
let ethernet = {
ports: discover_ports(),
lookup_by_interface_spec: function(interface) {
// Gather the glob patterns in all `ethernet: [ { select-ports: ... }]` specs,
// dedup them and turn them into one global regular expression pattern, then
// match this pattern against all known system ethernet ports, remember the
// related netdevs and return them as sorted, deduplicated array.
let globs = {};
map(interface.ethernet, eth => map(eth.select_ports, glob => globs[glob] = true));
lookup: function(globs) {
let re = regexp('^(' + join('|', map(keys(globs), glob => {
replace(glob, /[].*+?^${}()|[\\]/g, m => {
(m == '*') ? '.*' : ((m == '?') ? '.' : '\\' + m)
@@ -235,6 +228,24 @@ let ethernet = {
return sort(keys(matched));
},
lookup_by_interface_spec: function(interface) {
// Gather the glob patterns in all `ethernet: [ { select-ports: ... }]` specs,
// dedup them and turn them into one global regular expression pattern, then
// match this pattern against all known system ethernet ports, remember the
// related netdevs and return them as sorted, deduplicated array.
let globs = {};
map(interface.ethernet, eth => map(eth.select_ports, glob => globs[glob] = true));
return this.lookup(globs);
},
lookup_by_select_ports: function(select_ports) {
let globs = {};
map(select_ports, glob => globs[glob] = true);
return this.lookup(globs);
},
is_single_config: function(interface) {
let ipv4_mode = interface.ipv4 ? interface.ipv4.addressing : 'none';
let ipv6_mode = interface.ipv6 ? interface.ipv6.addressing : 'none';

View File

@@ -0,0 +1,9 @@
{% let eth_ports = ethernet.lookup_by_select_ports(ports.select_ports) %}
{% for (let port in eth_ports): %}
add network device
set network.@device[-1].name={{ s(port) }}
set network.@device[-1].ifname={{ s(port) }}
set network.@device[-1].speed={{ ports.speed }}
set network.@device[-1].duplex={{ ports.duplex == "full" ? true : false }}
{% endfor %}

View File

@@ -71,6 +71,9 @@
[metric]: state.metrics[metric] || {}
});
for (let i, ports in state.ethernet)
include('ethernet.uc', { location: '/ethernet/' + i, ports });
for (let i, radio in state.radios)
include('radio.uc', { location: '/radios/' + i, radio });

40
schema/ethernet.yml Normal file
View File

@@ -0,0 +1,40 @@
description:
This section defines the linkk speed and duplex mode of the physical copper/fiber
ports of the device.
type: object
properties:
select-ports:
description:
The list of physical network devices that shall be configured.
The names are logical ones and wildcardable.
type: array
items:
type: string
examples:
- LAN1
- LAN2
- LAN3
- LAN4
- LAN*
- WAN*
- "*"
speed:
description:
The link speed that shall be forced.
type: integer
enum:
- 10
- 100
- 1000
- 2500
- 5000
- 10000
default: 1000
duplex:
description:
The duplex mode that shall be forced.
type: string
enum:
- half
- full
default: full

View File

@@ -13,6 +13,10 @@ properties:
$ref: "https://ucentral.io/schema/v1/globals/"
definitions:
$ref: "https://ucentral.io/schema/v1/definitions/"
ethernet:
type: array
items:
$ref: "https://ucentral.io/schema/v1/ethernet/"
radios:
type: array
items:

View File

@@ -213,6 +213,75 @@ function instantiateDefinitions(location, value, errors) {
return value;
}
function instantiateEthernet(location, value, errors) {
if (type(value) == "object") {
let obj = {};
function parseSelectPorts(location, value, errors) {
if (type(value) == "array") {
function parseItem(location, value, errors) {
if (type(value) != "string")
push(errors, [ location, "must be of type string" ]);
return value;
}
return map(value, (item, i) => parseItem(location + "/" + i, item, errors));
}
if (type(value) != "array")
push(errors, [ location, "must be of type array" ]);
return value;
}
if (exists(value, "select-ports")) {
obj.select_ports = parseSelectPorts(location + "/select-ports", value["select-ports"], errors);
}
function parseSpeed(location, value, errors) {
if (type(value) != "int")
push(errors, [ location, "must be of type integer" ]);
if (!(value in [ 10, 100, 1000, 2500, 5000, 10000 ]))
push(errors, [ location, "must be one of 10, 100, 1000, 2500, 5000 or 10000" ]);
return value;
}
if (exists(value, "speed")) {
obj.speed = parseSpeed(location + "/speed", value["speed"], errors);
}
else {
obj.speed = 1000;
}
function parseDuplex(location, value, errors) {
if (type(value) != "string")
push(errors, [ location, "must be of type string" ]);
if (!(value in [ "half", "full" ]))
push(errors, [ location, "must be one of \"half\" or \"full\"" ]);
return value;
}
if (exists(value, "duplex")) {
obj.duplex = parseDuplex(location + "/duplex", value["duplex"], errors);
}
else {
obj.duplex = "full";
}
return obj;
}
if (type(value) != "object")
push(errors, [ location, "must be of type object" ]);
return value;
}
function instantiateRadioRates(location, value, errors) {
if (type(value) == "object") {
let obj = {};
@@ -4873,6 +4942,21 @@ function newUCentralState(location, value, errors) {
obj.definitions = instantiateDefinitions(location + "/definitions", value["definitions"], errors);
}
function parseEthernet(location, value, errors) {
if (type(value) == "array") {
return map(value, (item, i) => instantiateEthernet(location + "/" + i, item, errors));
}
if (type(value) != "array")
push(errors, [ location, "must be of type array" ]);
return value;
}
if (exists(value, "ethernet")) {
obj.ethernet = parseEthernet(location + "/ethernet", value["ethernet"], errors);
}
function parseRadios(location, value, errors) {
if (type(value) == "array") {
return map(value, (item, i) => instantiateRadio(location + "/" + i, item, errors));

View File

@@ -15,6 +15,12 @@
"definitions": {
"$ref": "#/$defs/definitions"
},
"ethernet": {
"type": "array",
"items": {
"$ref": "#/$defs/ethernet"
}
},
"radios": {
"type": "array",
"items": {
@@ -98,6 +104,46 @@
}
}
},
"ethernet": {
"type": "object",
"properties": {
"select-ports": {
"type": "array",
"items": {
"type": "string",
"examples": [
"LAN1",
"LAN2",
"LAN3",
"LAN4",
"LAN*",
"WAN*",
"*"
]
}
},
"speed": {
"type": "integer",
"enum": [
10,
100,
1000,
2500,
5000,
10000
],
"default": 1000
},
"duplex": {
"type": "string",
"enum": [
"half",
"full"
],
"default": "full"
}
}
},
"radio.rates": {
"type": "object",
"properties": {