diff --git a/renderer/templates/metric/dhcp_snooping.uc b/renderer/templates/metric/dhcp_snooping.uc index dede718..27af2b2 100644 --- a/renderer/templates/metric/dhcp_snooping.uc +++ b/renderer/templates/metric/dhcp_snooping.uc @@ -1,8 +1,11 @@ {% let interfaces = services.lookup_interfaces("dhcp-snooping") %} # DHCP Snooping configuration -{% for (let filter in dhcp_snooping.filters): %} -add_list event.dhcp.filter={{ filter }} +set event.dhcp=event +set event.dhcp.type=dhcp +set event.dhcp.filter='*' +{% for (let n, filter in dhcp_snooping.filters): %} +{{ n ? 'add_list' : 'set' }} event.dhcp.filter={{ filter }} {% endfor %} {% for (let interface in interfaces): %} diff --git a/renderer/templates/metric/wifi_frames.uc b/renderer/templates/metric/wifi_frames.uc new file mode 100644 index 0000000..a212ecb --- /dev/null +++ b/renderer/templates/metric/wifi_frames.uc @@ -0,0 +1,8 @@ + +# Wifi-frame reporting configuration +set event.wifi=event +set event.wifi.type=dhcp +set event.wifi.filter='*' +{% for (let n, filter in wifi_frames.filters): %} +{{ n ? 'add_list' : 'set' }} event.wifi.filter={{ filter }} +{% endfor %} diff --git a/schema/metrics.dhcp-snooping.yml b/schema/metrics.dhcp-snooping.yml new file mode 100644 index 0000000..9d874c0 --- /dev/null +++ b/schema/metrics.dhcp-snooping.yml @@ -0,0 +1,19 @@ +description: + DHCP snooping allows us to intercept DHCP packages on interface that are + bridged, where DHCP is not offered as a service by the AP. +type: object +properties: + filters: + description: + A list of the message types that shall be sent to the backend. + type: array + items: + type: string + enum: + - ack + - discover + - offer + - request + - solicit + - reply + - renew diff --git a/schema/metrics.health.yml b/schema/metrics.health.yml new file mode 100644 index 0000000..035f917 --- /dev/null +++ b/schema/metrics.health.yml @@ -0,0 +1,10 @@ +description: + Health check gets executed periodically and will report a health value + between 0-100 indicating how healthy the device thinks it is +type: object +properties: + interval: + description: + The reporting interval defined in seconds. + type: integer + minimum: 60 diff --git a/schema/metrics.statistics.yml b/schema/metrics.statistics.yml new file mode 100644 index 0000000..dde63ac --- /dev/null +++ b/schema/metrics.statistics.yml @@ -0,0 +1,19 @@ +description: + Statistics are traffic counters, neighbor tables, ... +type: object +properties: + interval: + description: + The reporting interval defined in seconds. + type: integer + minimum: 60 + types: + description: + A list of names of subsystems that shall be reported periodically. + type: array + items: + type: string + enum: + - ssids + - lldp + - clients diff --git a/schema/metrics.wifi-frames.yml b/schema/metrics.wifi-frames.yml new file mode 100644 index 0000000..e2cd1ad --- /dev/null +++ b/schema/metrics.wifi-frames.yml @@ -0,0 +1,22 @@ +description: + Define which types of ieee802.11 management frames shall be sent up to the + controller. +type: object +properties: + filters: + description: + A list of the management frames types that shall be sent to the backend. + type: array + items: + type: string + enum: + - probe + - auth + - assoc + - disassoc + - deauth + - local-deauth + - inactive-deauth + - key-mismatch + - beacon-report + - radar-detected diff --git a/schema/metrics.yml b/schema/metrics.yml index 2dfb849..4107644 100644 --- a/schema/metrics.yml +++ b/schema/metrics.yml @@ -4,53 +4,10 @@ description: type: object properties: statistics: - description: - Statistics are traffic counters, neighbor tables, ... - type: object - properties: - interval: - description: - The reporting interval defined in seconds. - type: integer - minimum: 60 - types: - description: - A list of names of subsystems that shall be reported periodically. - type: array - items: - type: string - enum: - - ssids - - lldp - - clients + $ref: "https://ucentral.io/schema/v1/metrics/statistics/" health: - description: - Health check gets executed periodically and will report a health value - between 0-100 indicating how healthy the device thinks it is - type: object - properties: - interval: - description: - The reporting interval defined in seconds. - type: integer - minimum: 60 + $ref: "https://ucentral.io/schema/v1/metrics/health/" + wifi-frames: + $ref: "https://ucentral.io/schema/v1/metrics/wifi-frames/" dhcp-snooping: - description: - DHCP snooping allows us to intercept DHCP packages on interface that are - bridged, where DHCP is not offered as a service by the AP. - type: object - properties: - filters: - description: - A list of the message types that shall be sent to the backend. - type: array - items: - type: string - enum: - - ack - - discover - - offer - - request - - solicit - - reply - - renew + $ref: "https://ucentral.io/schema/v1/metrics/dhcp-snooping/" diff --git a/schemareader.uc b/schemareader.uc index 428b48a..b79358d 100644 --- a/schemareader.uc +++ b/schemareader.uc @@ -116,7 +116,7 @@ function instantiateRadio(value) { function parseVariant0(value) { assert(type(value) == "int", "Property radio.channel must be of type integer"); assert(value <= 171, "Property radio.channel must be <= 171"); - assert(value >= 0, "Property radio.channel must be >= 0"); + assert(value >= 1, "Property radio.channel must be >= 1"); return value; } @@ -1507,85 +1507,111 @@ function instantiateService(value) { return obj; } +function instantiateMetricsStatistics(value) { + assert(type(value) == "object", "Property metrics.statistics must be of type object"); + + let obj = {}; + + if (exists(value, "interval")) { + assert(type(value["interval"]) == "int", "Property metrics.statistics.interval must be of type integer"); + assert(value["interval"] >= 60, "Property metrics.statistics.interval must be >= 60"); + obj.interval = value["interval"]; + } + + function parseTypes(value) { + assert(type(value) == "array", "Property metrics.statistics.types must be of type array"); + + return map(value, (item) => { + assert(type(item) == "string", "Items of metrics.statistics.types must be of type string"); + assert(item in [ "ssids", "lldp", "clients" ], "Items of metrics.statistics.types must be one of [ \"ssids\", \"lldp\", \"clients\" ]"); + return item; + }); + } + + if (exists(value, "types")) { + obj.types = parseTypes(value["types"]); + } + + return obj; +} + +function instantiateMetricsHealth(value) { + assert(type(value) == "object", "Property metrics.health must be of type object"); + + let obj = {}; + + if (exists(value, "interval")) { + assert(type(value["interval"]) == "int", "Property metrics.health.interval must be of type integer"); + assert(value["interval"] >= 60, "Property metrics.health.interval must be >= 60"); + obj.interval = value["interval"]; + } + + return obj; +} + +function instantiateMetricsWifiFrames(value) { + assert(type(value) == "object", "Property metrics.wifi-frames must be of type object"); + + let obj = {}; + + function parseFilters(value) { + assert(type(value) == "array", "Property metrics.wifi-frames.filters must be of type array"); + + return map(value, (item) => { + assert(type(item) == "string", "Items of metrics.wifi-frames.filters must be of type string"); + assert(item in [ "probe", "auth", "assoc", "disassoc", "deauth", "local-deauth", "inactive-deauth", "key-mismatch", "beacon-report", "radar-detected" ], "Items of metrics.wifi-frames.filters must be one of [ \"probe\", \"auth\", \"assoc\", \"disassoc\", \"deauth\", \"local-deauth\", \"inactive-deauth\", \"key-mismatch\", \"beacon-report\", \"radar-detected\" ]"); + return item; + }); + } + + if (exists(value, "filters")) { + obj.filters = parseFilters(value["filters"]); + } + + return obj; +} + +function instantiateMetricsDhcpSnooping(value) { + assert(type(value) == "object", "Property metrics.dhcp-snooping must be of type object"); + + let obj = {}; + + function parseFilters(value) { + assert(type(value) == "array", "Property metrics.dhcp-snooping.filters must be of type array"); + + return map(value, (item) => { + assert(type(item) == "string", "Items of metrics.dhcp-snooping.filters must be of type string"); + assert(item in [ "ack", "discover", "offer", "request", "solicit", "reply", "renew" ], "Items of metrics.dhcp-snooping.filters must be one of [ \"ack\", \"discover\", \"offer\", \"request\", \"solicit\", \"reply\", \"renew\" ]"); + return item; + }); + } + + if (exists(value, "filters")) { + obj.filters = parseFilters(value["filters"]); + } + + return obj; +} + function instantiateMetrics(value) { assert(type(value) == "object", "Property metrics must be of type object"); let obj = {}; - function parseStatistics(value) { - assert(type(value) == "object", "Property metrics.statistics must be of type object"); - - let obj = {}; - - if (exists(value, "interval")) { - assert(type(value["interval"]) == "int", "Property metrics.statistics.interval must be of type integer"); - assert(value["interval"] >= 60, "Property metrics.statistics.interval must be >= 60"); - obj.interval = value["interval"]; - } - - function parseTypes(value) { - assert(type(value) == "array", "Property metrics.statistics.types must be of type array"); - - return map(value, (item) => { - assert(type(item) == "string", "Items of metrics.statistics.types must be of type string"); - assert(item in [ "ssids", "lldp", "clients" ], "Items of metrics.statistics.types must be one of [ \"ssids\", \"lldp\", \"clients\" ]"); - return item; - }); - } - - if (exists(value, "types")) { - obj.types = parseTypes(value["types"]); - } - - return obj; - } - if (exists(value, "statistics")) { - obj.statistics = parseStatistics(value["statistics"]); - } - - function parseHealth(value) { - assert(type(value) == "object", "Property metrics.health must be of type object"); - - let obj = {}; - - if (exists(value, "interval")) { - assert(type(value["interval"]) == "int", "Property metrics.health.interval must be of type integer"); - assert(value["interval"] >= 60, "Property metrics.health.interval must be >= 60"); - obj.interval = value["interval"]; - } - - return obj; + obj.statistics = instantiateMetricsStatistics(value["statistics"]); } if (exists(value, "health")) { - obj.health = parseHealth(value["health"]); + obj.health = instantiateMetricsHealth(value["health"]); } - function parseDhcpSnooping(value) { - assert(type(value) == "object", "Property metrics.dhcp-snooping must be of type object"); - - let obj = {}; - - function parseFilters(value) { - assert(type(value) == "array", "Property metrics.dhcp-snooping.filters must be of type array"); - - return map(value, (item) => { - assert(type(item) == "string", "Items of metrics.dhcp-snooping.filters must be of type string"); - assert(item in [ "ack", "discover", "offer", "request", "solicit", "reply", "renew" ], "Items of metrics.dhcp-snooping.filters must be one of [ \"ack\", \"discover\", \"offer\", \"request\", \"solicit\", \"reply\", \"renew\" ]"); - return item; - }); - } - - if (exists(value, "filters")) { - obj.filters = parseFilters(value["filters"]); - } - - return obj; + if (exists(value, "wifi-frames")) { + obj.wifi_frames = instantiateMetricsWifiFrames(value["wifi-frames"]); } if (exists(value, "dhcp-snooping")) { - obj.dhcp_snooping = parseDhcpSnooping(value["dhcp-snooping"]); + obj.dhcp_snooping = instantiateMetricsDhcpSnooping(value["dhcp-snooping"]); } return obj; diff --git a/ucentral.schema.json b/ucentral.schema.json index 656b42e..a426305 100644 --- a/ucentral.schema.json +++ b/ucentral.schema.json @@ -131,7 +131,7 @@ { "type": "integer", "maximum": 171, - "minimum": 0 + "minimum": 1 }, { "type": "string", @@ -1254,57 +1254,92 @@ } } }, + "metrics.statistics": { + "type": "object", + "properties": { + "interval": { + "type": "integer", + "minimum": 60 + }, + "types": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ssids", + "lldp", + "clients" + ] + } + } + } + }, + "metrics.health": { + "type": "object", + "properties": { + "interval": { + "type": "integer", + "minimum": 60 + } + } + }, + "metrics.wifi-frames": { + "type": "object", + "properties": { + "filters": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "probe", + "auth", + "assoc", + "disassoc", + "deauth", + "local-deauth", + "inactive-deauth", + "key-mismatch", + "beacon-report", + "radar-detected" + ] + } + } + } + }, + "metrics.dhcp-snooping": { + "type": "object", + "properties": { + "filters": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ack", + "discover", + "offer", + "request", + "solicit", + "reply", + "renew" + ] + } + } + } + }, "metrics": { "type": "object", "properties": { "statistics": { - "type": "object", - "properties": { - "interval": { - "type": "integer", - "minimum": 60 - }, - "types": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "ssids", - "lldp", - "clients" - ] - } - } - } + "$ref": "#/$defs/metrics.statistics" }, "health": { - "type": "object", - "properties": { - "interval": { - "type": "integer", - "minimum": 60 - } - } + "$ref": "#/$defs/metrics.health" + }, + "wifi-frames": { + "$ref": "#/$defs/metrics.wifi-frames" }, "dhcp-snooping": { - "type": "object", - "properties": { - "filters": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "ack", - "discover", - "offer", - "request", - "solicit", - "reply", - "renew" - ] - } - } - } + "$ref": "#/$defs/metrics.dhcp-snooping" } } },