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 {