summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-mod-status
diff options
context:
space:
mode:
authorVladislav Grigoryev <vg.aetera@gmail.com>2021-08-05 03:50:37 +0300
committerVladislav Grigoryev <vg.aetera@gmail.com>2021-08-07 10:51:38 +0300
commit5cd9209636921d73ef140857b62ba57b03195e26 (patch)
tree2bb9f0496251764bb0eb5ccd8bc98a0415664fc3 /modules/luci-mod-status
parent39cc16d2eb8678b10deba7fca995f295674c43b1 (diff)
luci-mod-status: status/routing support for pbr
Provide comprehensive status information for routing. Rename the "Status > Routes" page to "Status > Routing". Unify sorting for the "Status" and "Network" menus. Add tabs for IPv4 and IPv6 and reorganize the contents. Display routing rules and their priorities for each protocol. Policy-based routing is an increasingly popular problem. Netifd natively supports policy-based routing: * The interface-specific options "ip4table" and "ip6table". * The routing rules using the "rule" and "rule6" sections. LuCI is missing the information about routing rules. Signed-off-by: Vladislav Grigoryev <vg.aetera@gmail.com>
Diffstat (limited to 'modules/luci-mod-status')
-rw-r--r--modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js99
-rw-r--r--modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json16
-rw-r--r--modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json5
3 files changed, 91 insertions, 29 deletions
diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js
index 6051b74c3b..91adae2434 100644
--- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js
+++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js
@@ -3,6 +3,7 @@
'require fs';
'require rpc';
'require validation';
+'require ui';
var callNetworkInterfaceDump = rpc.declare({
object: 'network.interface',
@@ -32,8 +33,10 @@ return view.extend({
callNetworkInterfaceDump(),
L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'neigh', 'show' ]), {}),
L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'route', 'show', 'table', 'all' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'rule', 'show' ]), {}),
L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'neigh', 'show' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'route', 'show', 'table', 'all' ]), {})
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'route', 'show', 'table', 'all' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'rule', 'show' ]), {})
]);
},
@@ -143,12 +146,32 @@ return view.extend({
return res;
},
+ parseRule: function(s) {
+ var lines = s.trim().split(/\n/),
+ res = [];
+
+ for (var i = 0; i < lines.length; i++) {
+ var m = lines[i].match(/^(\d+):\s+(.+)$/),
+ prio = m ? m[1] : null,
+ rule = m ? m[2] : null;
+
+ res.push([
+ prio,
+ rule
+ ]);
+ }
+
+ return res;
+ },
+
render: function(data) {
var networks = data[0],
ip4neigh = data[1].stdout || '',
ip4route = data[2].stdout || '',
- ip6neigh = data[3].stdout || '',
- ip6route = data[4].stdout || '';
+ ip4rule = data[3].stdout || '',
+ ip6neigh = data[4].stdout || '',
+ ip6route = data[5].stdout || '',
+ ip6rule = data[6].stdout || '';
var neigh4tbl = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
@@ -165,7 +188,14 @@ return view.extend({
E('th', { 'class': 'th' }, [ _('IPv4 gateway') ]),
E('th', { 'class': 'th' }, [ _('Metric') ]),
E('th', { 'class': 'th' }, [ _('Table') ]),
- E('th', { 'class': 'th' }, [ _('Protocol') ]),
+ E('th', { 'class': 'th' }, [ _('Protocol') ])
+ ])
+ ]);
+
+ var rule4tbl = E('table', { 'class': 'table' }, [
+ E('tr', { 'class': 'tr table-titles' }, [
+ E('th', { 'class': 'th' }, [ _('Priority') ]),
+ E('th', { 'class': 'th' }, [ _('Rule') ])
])
]);
@@ -184,31 +214,62 @@ return view.extend({
E('th', { 'class': 'th' }, [ _('Source') ]),
E('th', { 'class': 'th' }, [ _('Metric') ]),
E('th', { 'class': 'th' }, [ _('Table') ]),
- E('th', { 'class': 'th' }, [ _('Protocol') ]),
+ E('th', { 'class': 'th' }, [ _('Protocol') ])
+ ])
+ ]);
+
+ var rule6tbl = E('table', { 'class': 'table' }, [
+ E('tr', { 'class': 'tr table-titles' }, [
+ E('th', { 'class': 'th' }, [ _('Priority') ]),
+ E('th', { 'class': 'th' }, [ _('Rule') ])
])
]);
cbi_update_table(neigh4tbl, this.parseNeigh(ip4neigh, networks, false));
cbi_update_table(route4tbl, this.parseRoute(ip4route, networks, false));
+ cbi_update_table(rule4tbl, this.parseRule(ip4rule, networks, false));
cbi_update_table(neigh6tbl, this.parseNeigh(ip6neigh, networks, true));
cbi_update_table(route6tbl, this.parseRoute(ip6route, networks, true));
-
- return E([], [
- E('h2', {}, [ _('Routes') ]),
+ cbi_update_table(rule6tbl, this.parseRule(ip6rule, networks, false));
+
+ var view = E([], [
+ E('style', { 'type': 'text/css' }, [
+ '.cbi-tooltip-container, span.jump { border-bottom:1px dotted #00f;cursor:pointer }',
+ 'ul { list-style:none }',
+ '.references { position:relative }',
+ '.references .cbi-tooltip { left:0!important;top:1.5em!important }',
+ 'h4>span { font-size:90% }'
+ ]),
+
+ E('h2', {}, [ _('Routing') ]),
E('p', {}, [ _('The following rules are currently active on this system.') ]),
+ E('div', {}, [
+ E('div', { 'data-tab': 'ipv4routing', 'data-tab-title': _('IPv4 Routing') }, [
+ E('h3', {}, [ _('ARP') ]),
+ neigh4tbl,
+
+ E('h3', {}, _('Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes')),
+ route4tbl,
+
+ E('h3', {}, _('Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Rules')),
+ rule4tbl
+ ]),
+ E('div', { 'data-tab': 'ipv6routing', 'data-tab-title': _('IPv6 Routing') }, [
+ E('h3', {}, [ _('IPv6 Neighbours') ]),
+ neigh6tbl,
+
+ E('h3', {}, _('Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes')),
+ route6tbl,
+
+ E('h3', {}, _('Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Rules')),
+ rule6tbl
+ ])
+ ])
+ ]);
- E('h3', {}, [ _('ARP') ]),
- neigh4tbl,
-
- E('h3', {}, _('Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes')),
- route4tbl,
-
- E('h3', {}, [ _('IPv6 Neighbours') ]),
- neigh6tbl,
+ ui.tabs.initTabGroup(view.lastElementChild.childNodes);
- E('h3', {}, _('Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes')),
- route6tbl
- ]);
+ return view;
},
handleSaveApply: null,
diff --git a/modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json b/modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json
index 0f066e67ad..1e6556bab2 100644
--- a/modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json
+++ b/modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json
@@ -11,27 +11,27 @@
}
},
- "admin/status/iptables": {
- "title": "Firewall",
+ "admin/status/routes": {
+ "title": "Routing",
"order": 2,
"action": {
"type": "view",
- "path": "status/iptables"
+ "path": "status/routes"
},
"depends": {
- "acl": [ "luci-mod-status-firewall" ]
+ "acl": [ "luci-mod-status-routes" ]
}
},
- "admin/status/routes": {
- "title": "Routes",
+ "admin/status/iptables": {
+ "title": "Firewall",
"order": 3,
"action": {
"type": "view",
- "path": "status/routes"
+ "path": "status/iptables"
},
"depends": {
- "acl": [ "luci-mod-status-routes" ]
+ "acl": [ "luci-mod-status-firewall" ]
}
},
diff --git a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json
index 3e7d823014..63ff83132d 100644
--- a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json
+++ b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json
@@ -44,11 +44,12 @@
},
"luci-mod-status-routes": {
- "description": "Grant access to the system route status",
+ "description": "Grant access to routing status",
"read": {
"file": {
"/sbin/ip -[46] neigh show": [ "exec" ],
- "/sbin/ip -[46] route show table all": [ "exec" ]
+ "/sbin/ip -[46] route show table all": [ "exec" ],
+ "/sbin/ip -[46] rule show": [ "exec" ]
},
"ubus": {
"file": [ "exec" ]