diff --git a/src/lib/cmdgen.c b/src/lib/cmdgen.c
index 113f4dd..4ac6c9a 100644
--- a/src/lib/cmdgen.c
+++ b/src/lib/cmdgen.c
@@ -363,10 +363,12 @@ struct lyd_node *get_node_from_sr(const struct lyd_node *startcmd_node, char *no
else
ret = sr_get_data(sr_session, xpath, 0, 0, 0, &sr_data);
if (ret != SR_ERR_OK) {
- fprintf(stderr,
- "%s: failed to get node data from sysrepo ds."
- " xpath = \"%s\": %s\n",
- __func__, xpath, sr_strerror(ret));
+ if (ret != SR_ERR_NOT_FOUND) {
+ fprintf(stderr,
+ "%s: failed to get node data from sysrepo ds."
+ " xpath = \"%s\": %s\n",
+ __func__, xpath, sr_strerror(ret));
+ }
return NULL;
}
return sr_data->tree;
@@ -407,6 +409,8 @@ int find_netns(struct lyd_node *startcmd, char **netns)
return EXIT_FAILURE;
}
}
+ if (!strcmp(link_startcmd->schema->module->name, "iproute2-tc-filter"))
+ link_startcmd = lyd_parent(link_startcmd);
struct lyd_node *netns_dnode = get_node_from_sr(link_startcmd, "netns");
// if the netns_dnode does not exist in sysrepo, then this is create, we get the netns from
// the startcmd
diff --git a/tests/cases/test_tc_filter.sh b/tests/cases/test_tc_filter.sh
index e6b3dfa..50b84b2 100755
--- a/tests/cases/test_tc_filter.sh
+++ b/tests/cases/test_tc_filter.sh
@@ -19,6 +19,8 @@ clean_up(){
ip link del if_tc_f2 2>/dev/null
ip link del if_tc_f3 2>/dev/null
ip link del if_tc_f4 2>/dev/null
+ ip -n tc_filter_red link delete name if_tc_f5_red
+ ip netns del tc_filter_red
}
ret=0
@@ -33,7 +35,7 @@ echo "---------------------"
sysrepocfg -d running --edit tests/cases/test_tc_filter_data.xml || ret=$?
# Check if sysrepocfg command failed
if [ -n "$ret" ] && [ "$ret" -ne 0 ]; then
- echo "TEST-ERROR: failed to create filter in sysrepo datastore"
+ echo "TEST-ERROR:TC-FILTER: failed to create filter in sysrepo datastore"
clean_up
exit "$ret"
fi
@@ -41,9 +43,9 @@ fi
output=$(tc filter show dev if_tc_f4 ingress)
# Step 2: Check if dev-filter created
if echo "$output" | grep -q "filter protocol ip pref 10 flower chain 0"; then
- echo "TEST-INFO: dev-filter for if_tc_f4 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: dev-filter for if_tc_f4 created successfully (OK)"
else
- echo "TEST-ERROR: Failed to create dev-filter for if_tc_f4 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create dev-filter for if_tc_f4 (FAIL)"
clean_up
exit 1
fi
@@ -51,9 +53,9 @@ fi
output2=$(tc filter show block 10)
# Step 3: Check if share-block-filter is created
if echo "$output2" | grep -q "filter protocol ip pref 10 flower chain 0"; then
- echo "TEST-INFO: share-block-filter for if_tc_f3 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: share-block-filter for if_tc_f3 created successfully (OK)"
else
- echo "TEST-ERROR: Failed to create share-block-filter for if_tc_f3 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create share-block-filter for if_tc_f3 (FAIL)"
clean_up
exit 1
fi
@@ -62,9 +64,9 @@ output3=$(tc filter show dev if_tc_f2)
# Step 3: Check if qdisc-filter u32 is created
if echo "$output3" | grep -q "filter parent 8002: protocol ip pref 20 u32 chain 0"; then
- echo "TEST-INFO: qdisc-filter (u32) for if_tc_f1 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: qdisc-filter (u32) for if_tc_f1 created successfully (OK)"
else
- echo "TEST-ERROR: Failed to create qdisc-filter (u32) for if_tc_f1 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create qdisc-filter (u32) for if_tc_f1 (FAIL)"
clean_up
exit 1
fi
@@ -73,9 +75,20 @@ fi
output4=$(tc filter show dev if_tc_f1)
# Step 3: Check if qdisc-filter flower is created
if echo "$output4" | grep -q "filter parent 8001: protocol ip pref 20 flower chain 0"; then
- echo "TEST-INFO: qdisc-filter (flower) for if_tc_f1 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: qdisc-filter (flower) for if_tc_f1 created successfully (OK)"
else
- echo "TEST-ERROR: Failed to create qdisc-filter (flower) for if_tc_f1 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create qdisc-filter (flower) for if_tc_f1 (FAIL)"
+ clean_up
+ exit 1
+fi
+
+
+output=$(tc -n tc_filter_red filter show dev if_tc_f5_red ingress)
+# Step 4: Check if netns dev-filter created
+if echo "$output" | grep -q "filter protocol ip pref 101 flower chain 0"; then
+ echo "TEST-INFO:TC-FILTER: netns dev-filter for if_tc_f5_red created successfully (OK)"
+else
+ echo "TEST-ERROR:TC-FILTER: Failed to create netns dev-filter for if_tc_f5_red (FAIL)"
clean_up
exit 1
fi
@@ -99,32 +112,32 @@ sysrepocfg -C startup -d running || ret=$?
output=$(tc filter show dev if_tc_f4 ingress 2>/dev/null)
# Step 2: Check if dev-filter is still there
if echo "$output" | grep -q "filter protocol ip pref 10 flower chain 0"; then
- echo "TEST-ERROR: Failed to delete dev-filter for if_tc_f4 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to delete dev-filter for if_tc_f4 (FAIL)"
clean_up
exit 1
else
- echo "TEST-INFO: dev-filter for if_tc_f4 deleted successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: dev-filter for if_tc_f4 deleted successfully (OK)"
fi
output2=$(tc filter show block 10 2>/dev/null)
# Step 3: Check if share-block-filter is still there
if echo "$output2" | grep -q "filter protocol ip pref 10 flower chain 0"; then
- echo "TEST-ERROR: Failed to delete share-block-filter for if_tc_f3 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to delete share-block-filter for if_tc_f3 (FAIL)"
clean_up
exit 1
else
- echo "TEST-INFO: share-block-filter for if_tc_f1 deleted successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: share-block-filter for if_tc_f1 deleted successfully (OK)"
fi
output3=$(tc filter show dev if_tc_f2 2>/dev/null)
# Step 3: Check if qdisc-filter u32 is deleted
if echo "$output3" | grep -q "filter parent 8002: protocol ip pref 20 u32 chain 0"; then
- echo "TEST-ERROR: Failed to create qdisc-filter (u32) for if_tc_f1 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create qdisc-filter (u32) for if_tc_f1 (FAIL)"
clean_up
exit 1
else
- echo "TEST-INFO: qdisc-filter (u32) for if_tc_f1 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: qdisc-filter (u32) for if_tc_f1 created successfully (OK)"
fi
@@ -132,14 +145,24 @@ fi
output4=$(tc filter show dev if_tc_f1 2>/dev/null)
# Step 3: Check if qdisc-filter flower is created
if echo "$output4" | grep -q "filter parent 8001: protocol ip pref 20 flower chain 0"; then
- echo "TEST-ERROR: Failed to create qdisc-filter (flower) for if_tc_f1 (FAIL)"
+ echo "TEST-ERROR:TC-FILTER: Failed to create qdisc-filter (flower) for if_tc_f1 (FAIL)"
clean_up
exit 1
else
- echo "TEST-INFO: qdisc-filter (flower) for if_tc_f1 created successfully (OK)"
+ echo "TEST-INFO:TC-FILTER: qdisc-filter (flower) for if_tc_f1 created successfully (OK)"
fi
+output=$(tc -n tc_filter_red filter show dev if_tc_f5_red ingress 2>/dev/null)
+# Step 2: Check if dev-filter is still there
+if echo "$output" | grep -q "filter protocol ip pref 101 flower chain 0"; then
+ echo "TEST-ERROR:TC-FILTER: Failed to delete netns dev-filter for if_tc_f5_red (FAIL)"
+ clean_up
+ exit 1
+else
+ echo "TEST-INFO:TC-FILTER: netns dev-filter for if_tc_f5_red deleted successfully (OK)"
+fi
+
# delete the Qdiscs and links
sysrepocfg -C startup -d running -m iproute2-tc-qdisc || ret=$?
sysrepocfg -C startup -d running -m iproute2-ip-link || ret=$?
diff --git a/tests/cases/test_tc_filter_data.xml b/tests/cases/test_tc_filter_data.xml
index cbc35b4..66543e9 100644
--- a/tests/cases/test_tc_filter_data.xml
+++ b/tests/cases/test_tc_filter_data.xml
@@ -1,3 +1,8 @@
+
+
+ tc_filter_red
+
+
@@ -20,12 +25,19 @@
dummy
up
+
+ if_tc_f5_red
+ dummy
+ up
+ tc_filter_red
+
if_tc_f1
8001:
ip
+ 1
20
@@ -61,6 +73,7 @@
if_tc_f2
8002:
ip
+ 1
20
@@ -77,6 +90,7 @@
if_tc_f4
ingress
ip
+ 1
10
@@ -94,9 +108,32 @@
+
+ if_tc_f5_red
+ ingress
+ ip
+ tc_filter_red
+
+ 101
+
+
+ icmp
+ 11.21.11.21/32
+
+ pass
+
+
+
+ 201
+
+ drop
+
+
+
10
ip
+ 1
10
@@ -111,6 +148,7 @@
if_tc_f1
8001:
8001:20
+ 1
20mbit
@@ -119,6 +157,7 @@
if_tc_f1
8001:
8001:30
+ 1
30mbit
@@ -127,6 +166,7 @@
if_tc_f1
8001:
8001:40
+ 1
40mbit
@@ -135,6 +175,7 @@
if_tc_f2
8002:
8002:20
+ 1
20mbit
@@ -145,12 +186,14 @@
if_tc_f1
root
+ 1
8001:
htb
if_tc_f1
8001:20
+ 1
pfifo
1002
@@ -159,6 +202,7 @@
if_tc_f1
8001:30
+ 1
pfifo
1003
@@ -167,6 +211,7 @@
if_tc_f1
8001:40
+ 1
pfifo
1004
@@ -175,16 +220,24 @@
if_tc_f2
root
+ 1
8002:
htb
if_tc_f3
clsact
+ 1
10
if_tc_f4
ingress
+ 1
+
+
+ if_tc_f5_red
+ ingress
+ tc_filter_red
diff --git a/tests/cases/test_tc_qdisc_data.xml b/tests/cases/test_tc_qdisc_data.xml
index e73e0fc..516c684 100644
--- a/tests/cases/test_tc_qdisc_data.xml
+++ b/tests/cases/test_tc_qdisc_data.xml
@@ -29,6 +29,7 @@
if_tc3
root
+ 1
pfifo
999
@@ -37,6 +38,7 @@
if_tc4
root
+ 1
fq_codel
1001
@@ -47,6 +49,7 @@
if_tc5
root
+ 1
tbf
3200bps
@@ -57,12 +60,14 @@
if_tc1
clsact
+ 1
10
30
if_tc2
ingress
+ 1
10
diff --git a/yang/iproute2-tc-filter.yang b/yang/iproute2-tc-filter.yang
index 57df73c..094adda 100644
--- a/yang/iproute2-tc-filter.yang
+++ b/yang/iproute2-tc-filter.yang
@@ -4,8 +4,10 @@ module iproute2-tc-filter {
prefix "filter";
import ietf-inet-types { prefix inet; }
+ import okda-onmcli-extensions{ prefix onmcli; }
import iproute2-cmdgen-extensions { prefix ipr2cgen; }
import iproute2-ip-link { prefix iplink; }
+ import iproute2-ip-netns { prefix ipnetns; }
import iproute2-tc-qdisc { prefix qdisc; }
organization "Okda Networks";
@@ -23,6 +25,19 @@ module iproute2-tc-filter {
}
grouping filter-common {
+ leaf netns {
+ ipr2cgen:not-cmd-arg;
+ onmcli:key-default-val "1";
+ ipr2cgen:oper-default-val "1";
+ type union {
+ type ipnetns:netns-ref;
+ type enumeration {
+ enum "1";
+ }
+ }
+ default "1";
+ description "network namespace name";
+ }
leaf protocol {
type enumeration {
enum "ip";
@@ -280,13 +295,13 @@ module iproute2-tc-filter {
container tc-filters {
description "Container for all tc filter configurations.";
list qdisc-filter {
- key "dev parent";
+ key "dev parent netns";
description "filter that is applied to qdisc";
leaf dev {
type leafref {
path '/qdisc:qdiscs/qdisc:qdisc/qdisc:dev';
}
- description "Name of device 'interface' where the qdisc is attached to.";
+ description "Name of device 'link' where the qdisc is attached to, the link must have qdisc attached to it.";
mandatory true;
}
leaf parent {
@@ -302,7 +317,7 @@ module iproute2-tc-filter {
}
list dev-filter {
description "A list of filters.";
- key "dev direction";
+ key "dev direction netns";
leaf dev {
type leafref {
path '/qdisc:qdiscs/qdisc:special-qdisc/qdisc:dev';
@@ -317,11 +332,12 @@ module iproute2-tc-filter {
enum "egress";
}
}
+
uses filter-common;
uses filter-rule;
}
list shared-block-filter {
- key "block";
+ key "block netns";
leaf block {
type union{
type leafref {
diff --git a/yang/iproute2-tc-qdisc.yang b/yang/iproute2-tc-qdisc.yang
index b907c59..bcf5c19 100644
--- a/yang/iproute2-tc-qdisc.yang
+++ b/yang/iproute2-tc-qdisc.yang
@@ -3,16 +3,17 @@ module iproute2-tc-qdisc {
namespace "urn:okda:iproute2:tc:qdisc";
prefix "qdisc";
- import iproute2-ip-link {prefix iplink;}
import okda-onmcli-extensions{ prefix onmcli; }
+ import iproute2-ip-link {prefix iplink;}
import iproute2-cmdgen-extensions { prefix ipr2cgen; }
+ import iproute2-ip-netns { prefix ipnetns; }
organization "Okda Networks";
contact
"Authors: Amjad Daraiseh
- Ali Aqrabawi ";
-
+ Ali Aqrabawi ";
+
description
"This module contain the iproute2 'tc qdisc' configurations.
@@ -35,11 +36,11 @@ module iproute2-tc-qdisc {
}
}
type string {
- // Temporary to allow referencing a qdisc
+ // Temporary to allow referencing a qdisc
pattern '\d+:\d+';
}
type string {
- // Temporary to allow referencing a qdisc
+ // Temporary to allow referencing a qdisc
pattern ':\d+';
}
}
@@ -256,7 +257,7 @@ module iproute2-tc-qdisc {
ipr2cgen:oper-cmd "tc qdisc list";
ipr2cgen:oper-stop-if "{\"kind\": [\"ingress\", \"clsact\", \"noqueue\", \"mq\"]}";
ipr2cgen:include-all-on-update;
- key "dev parent";
+ key "dev parent netns";
description "List of qdisc configurations.";
leaf dev {
@@ -268,6 +269,19 @@ module iproute2-tc-qdisc {
type parent-id;
description "[parent_id 'e.g 8001:1' | root ] Location of the qdisc in the traffic control hierarchy. ";
}
+ leaf netns {
+ ipr2cgen:not-cmd-arg;
+ onmcli:key-default-val "1";
+ ipr2cgen:oper-default-val "1";
+ type union {
+ type ipnetns:netns-ref;
+ type enumeration {
+ enum "1";
+ }
+ }
+ default "1";
+ description "network namespace name";
+ }
leaf handle {
type string {
pattern '[0-9a-fA-F]+:';
@@ -311,7 +325,7 @@ module iproute2-tc-qdisc {
description "The kind of qdisc to apply.";
}
container fifo-options {
- ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"tbf\",
+ ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"tbf\",
\"htb\", \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo-fast\", \"multiq\", \"netem\",
\"red\", \"sfq\", \"sfb\", \"ATM\", \"cbq\", \"drr\", \"dsmark\", \"ets\", \"hfsc\", \"prio\", \"qfq\"]}";
ipr2cgen:oper-sub-jobj "options";
@@ -426,8 +440,8 @@ module iproute2-tc-qdisc {
uses codel-stats;
}
container tbf-options {
- ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"htb\",
- \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
+ ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"htb\",
+ \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
\"netem\", \"red\", \"sfq\", \"sfb\", \"ATM\", \"cbq\", \"drr\", \"dsmark\", \"ets\", \"hfsc\", \"prio\" , \"qfq\"]}";
ipr2cgen:oper-sub-jobj "options";
when "../qdisc-kind = 'tbf'";
@@ -553,8 +567,8 @@ module iproute2-tc-qdisc {
}
container htb-options {
- ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"tbf\",
- \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
+ ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"ingress\", \"clsact\", \"tbf\",
+ \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
\"netem\", \"red\", \"sfq\", \"sfb\", \"ATM\", \"cbq\", \"drr\", \"dsmark\", \"ets\", \"hfsc\", \"prio\" , \"qfq\"]}";
ipr2cgen:oper-sub-jobj "options";
when "../qdisc-kind = 'htb'";
@@ -598,10 +612,10 @@ module iproute2-tc-qdisc {
ipr2cgen:cmd-update "tc qdisc replace";
ipr2cgen:include-all-on-update;
ipr2cgen:oper-cmd "tc qdisc list";
- ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"tbf\",
- \"htb\", \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
+ ipr2cgen:oper-stop-if "{\"kind\": [\"choke\", \"codel\", \"fq_codel\", \"tbf\",
+ \"htb\", \"hhf\", \"fq\", \"fq_pie\", \"pie\", \"gred\", \"mqprio\", \"pfifo_fast\", \"bfifo\", \"pfifo\", \"multiq\",
\"netem\", \"red\", \"sfq\", \"sfb\", \"ATM\", \"cbq\", \"drr\", \"dsmark\", \"ets\", \"hfsc\", \"prio\" , \"qfq\", \"noqueue\", \"mq\"]}";
- key "dev qdisc-kind";
+ key "dev qdisc-kind netns";
unique "dev";
description "List of qdisc configurations.";
leaf dev {
@@ -624,6 +638,19 @@ module iproute2-tc-qdisc {
}
}
}
+ leaf netns {
+ ipr2cgen:not-cmd-arg;
+ onmcli:key-default-val "1";
+ ipr2cgen:oper-default-val "1";
+ type union {
+ type ipnetns:netns-ref;
+ type enumeration {
+ enum "1";
+ }
+ }
+ default "1";
+ description "network namespace name";
+ }
leaf ingress_block {
type uint32;
description "Ingress tc shared block ID";
@@ -633,7 +660,7 @@ module iproute2-tc-qdisc {
type uint32;
description "egress tc shared block ID";
}
- uses qdisc-stats;
+ uses qdisc-stats;
}
}
container classes {
@@ -643,7 +670,7 @@ module iproute2-tc-qdisc {
ipr2cgen:cmd-delete "tc class del";
ipr2cgen:cmd-update "tc class change";
ipr2cgen:include-all-on-update;
- key "dev parent classid";
+ key "dev parent classid netns";
leaf dev {
type iplink:link-ref;
description
@@ -663,6 +690,19 @@ module iproute2-tc-qdisc {
description
"";
}
+ leaf netns {
+ ipr2cgen:not-cmd-arg;
+ onmcli:key-default-val "1";
+ ipr2cgen:oper-default-val "1";
+ type union {
+ type ipnetns:netns-ref;
+ type enumeration {
+ enum "1";
+ }
+ }
+ default "1";
+ description "network namespace name";
+ }
choice qdisc-options {
mandatory true;
container htb {