Skip to content

Commit

Permalink
config,oper: support for ip rule config and oper load
Browse files Browse the repository at this point in the history
Signed-off-by: ali-aqrabawi <[email protected]>
  • Loading branch information
Ali-aqrabawi committed May 15, 2024
1 parent ba27285 commit 49db039
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/iproute2_sysrepo.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct yang_module {
{ "iproute2-ip-nexthop", "/iproute2-ip-nexthop:nexthops" },
{ "iproute2-ip-netns", "/iproute2-ip-netns:netnses" },
{ "iproute2-ip-route", "/iproute2-ip-route:routes" },
{ "iproute2-ip-rule", "/iproute2-ip-rule:rules" },
{ "iproute2-tc-qdisc", "/iproute2-tc-qdisc:qdiscs" },
{ "iproute2-tc-filter", "/iproute2-tc-filter:tc-filters" } };

Expand Down
44 changes: 43 additions & 1 deletion src/lib/cmdgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ typedef enum {
ADD_STATIC_ARG_EXT,
REPLACE_ON_UPDATE_EXT,
INCLUDE_ALL_ON_DELETE,
INCLUDE_ALL_ON_UPDATE_EXT,

} extension_t;

Expand All @@ -84,6 +85,7 @@ char *yang_ext_map[] = { [CMD_START_EXT] = "cmd-start",
[ON_UPDATE_INCLUDE_EXT] = "on-update-include",
[ADD_STATIC_ARG_EXT] = "add-static-arg",
[REPLACE_ON_UPDATE_EXT] = "replace-on-update",
[INCLUDE_ALL_ON_UPDATE_EXT] = "include-all-on-update",
[INCLUDE_ALL_ON_DELETE] = "include-all-on-delete",
[NOT_DEPENDENCY_EXT] = "not-dependency" };

Expand Down Expand Up @@ -917,7 +919,7 @@ char *lyd2cmd_line(struct lyd_node *startcmd_node, char *oper2cmd_prefix[3])
}

if (op_val == UPDATE_OPR &&
(get_extension(REPLACE_ON_UPDATE_EXT, startcmd_node, NULL) == EXIT_SUCCESS)) {
(get_extension(INCLUDE_ALL_ON_UPDATE_EXT, startcmd_node, NULL) == EXIT_SUCCESS)) {
ext_onupdate_replace_hdlr(&startcmd_node);
}
// add cmd prefix to the cmd_line
Expand Down Expand Up @@ -1081,6 +1083,7 @@ int add_cmd_info_core(struct cmd_info **cmds, int *cmd_idx, struct lyd_node *sta
char *oper2cmd_prefix[3] = { NULL };
char *cmd_line = NULL, *rollback_cmd_line = NULL;
struct lyd_node *rollback_dnode = NULL;
struct lyd_node *del_startcmd_node = NULL;
// first get the add, update, delete cmds prefixis from schema extensions
if (get_extension(CMD_ADD_EXT, startcmd_node, &oper2cmd_prefix[ADD_OPR]) != EXIT_SUCCESS) {
fprintf(stderr,
Expand Down Expand Up @@ -1109,6 +1112,43 @@ int add_cmd_info_core(struct cmd_info **cmds, int *cmd_idx, struct lyd_node *sta
goto cleanup;
}

// if this node is replace-on-update (where we need to delete and recreate the node in iproute2)
// first create a del_node with del operation then generate and add the command to the cmds before
// the original update cmd.
if (get_extension(REPLACE_ON_UPDATE_EXT, startcmd_node, NULL) == EXIT_SUCCESS &&
get_operation(startcmd_node) == UPDATE_OPR) {
//
ret = lyd_dup_single(startcmd_node, NULL, LYD_DUP_RECURSIVE, &del_startcmd_node);
if (ret != LY_SUCCESS) {
fprintf(
stderr,
"%s: ipr2cgen:failed to create del_startcmd_node: failed to duplicate node %s: %s\n",
__func__, startcmd_node->schema->name, ly_strerrcode(ret));
ret = EXIT_FAILURE;
goto cleanup;
}
// set the operation of the del_startcmd to delete.
struct lyd_meta *del_meta = lyd_find_meta(del_startcmd_node->meta, NULL, "yang:operation");
ret = lyd_change_meta(del_meta, "delete");
if (ret != LY_SUCCESS) {
fprintf(
stderr,
"%s: ipr2cgen:failed to add delete operation to del_startcmd_node for node %s: %s \n",
__func__, startcmd_node->schema->name, ly_strerrcode(ret));
ret = EXIT_FAILURE;
goto cleanup;
}
char *del_cmd_line = NULL;
del_cmd_line = lyd2cmd_line(del_startcmd_node, oper2cmd_prefix);
if (del_cmd_line == NULL) {
fprintf(stderr, "%s: failed to generate cmd for del_startcmd node \"%s\" \n", __func__,
startcmd_node->schema->name);
ret = EXIT_FAILURE;
goto cleanup;
}
add_command(cmds, cmd_idx, del_cmd_line, del_cmd_line);
}

cmd_line = lyd2cmd_line(startcmd_node, oper2cmd_prefix);
if (cmd_line == NULL) {
fprintf(stderr, "%s: failed to generate ipr2 cmd for node \"%s\" \n", __func__,
Expand Down Expand Up @@ -1161,6 +1201,8 @@ int add_cmd_info_core(struct cmd_info **cmds, int *cmd_idx, struct lyd_node *sta
free(rollback_cmd_line);
if (rollback_dnode)
lyd_free_all(rollback_dnode);
if (del_startcmd_node)
lyd_free_all(del_startcmd_node);
if (oper2cmd_prefix[ADD_OPR])
free(oper2cmd_prefix[ADD_OPR]);
if (oper2cmd_prefix[UPDATE_OPR])
Expand Down
120 changes: 120 additions & 0 deletions tests/cases/test_ip_rule.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/bin/bash

#####################################################################
# Testbed Script for Testing iproute2-sysrepo "ip rule" functionality
#####################################################################
# This script performs a series of tests on the iproute2-sysrepo
# functionality related to IP rule manipulation. It verifies the
# creation, deletion, and updating of IP rule by iproute2-sysrepo
# using sysrepocfg commands and checks if the operations are
# successful.
#
# Test Steps:
# 1. Test creating rule
# 2. Test updating rule
# 3. Test deleting rule
#####################################################################
clean_up(){
ip rule del pref 200 from 1.1.1.1/32 2>/dev/null
ip rule del pref 201 to 1.1.1.1/32 2>/dev/null
}

ret=0
####################################################################
# Test: Create IP rule
####################################################################
echo "--------------------"
echo "[1] Test rule CREATE"
echo "---------------------"

# Step 1: Add IP rule to RUNNING data store
sysrepocfg -d running --edit tests/cases/test_ip_rule_data.xml || ret=$?
# Check if sysrepocfg command failed
if [ -n "$ret" ] && [ "$ret" -ne 0 ]; then
echo "TEST-ERROR: failed to create rules in sysrepo datastore"
clean_up
exit "$ret"
fi

# Step 2: Check if first rule is created
if ip rule show pref 200 from 1.1.1.1/32 | grep -q 'from 1.1.1.1'; then
echo "TEST-INFO: rule from 1.1.1.1/32 created successfully (OK)"
else
echo "TEST-ERROR: Failed to create rule from 1.1.1.1/32 (FAIL)"
clean_up
exit 1
fi


# Step 3: Check if second rule is created
if ip rule show pref 201 to 1.1.1.1/32 | grep -q 'to 1.1.1.1'; then
echo "TEST-INFO: rule to 1.1.1.1/32 created successfully (OK)"
else
echo "TEST-ERROR: Failed to create rule to 1.1.1.1/32 (FAIL)"
clean_up
exit 1
fi

####################################################################
# Test: Update IP rule
####################################################################
echo "--------------------"
echo "[1] Test rule UPDATE"
echo "---------------------"
ip rule show 11.11.11.11/32
# Step 1: change table
sysrepocfg -S '/iproute2-ip-rule:rules/rule[pref="201"][from="0.0.0.0/0"][to="1.1.1.1/32"][tos="default"][fwmark="0x00"]/action/table' --value 100

# Step 3: Capture table id for the rule
table_id=$(ip rule show pref 201 to 1.1.1.1/32 | grep -oP '(?<=lookup )\d+' | head -n 1)

# Step 4: Check if the rule table was updated to 100
if [ -z "$table_id" ]; then
echo "TEST-ERROR: Failed to retrieve table_id for rule to 1.1.1.1/32"
clean_up
exit 1
fi

if [ "$table_id" -eq 100 ]; then
echo "TEST-INFO: table_id for rule to 1.1.1.1/32 updated successfully (OK)"
else
echo "TEST-ERROR: Failed to update table_id for rule to 1.1.1.1/32, table_id = $table_id (FAIL)"
clean_up
exit 1
fi

####################################################################
# Test: Delete IP rule
####################################################################
echo "--------------------"
echo "[1] Test rule DELETE"
echo "---------------------"

# Step 1: delete the rules from sysrepo
sysrepocfg -C startup -d running || ret=$?

# Attempt to delete the first rule
ip rule del pref 200 from 1.1.1.1/32 2>/dev/null

# if cmd exist failed (no such process) then the rule deleted successfully.
if [ $? -ne 0 ]; then
echo "Rule from 1.1.1.1/32 deleted successfully (OK)"
else
echo "Failed to delete rule from 1.1.1.1/32 (FAIL)"
clean_up
exit 1
fi

# Attempt to delete the second rule
ip rule del pref 201 to 1.1.1.1/32 2>/dev/null

# if cmd exist failed (no such process) then the rule deleted successfully.
if [ $? -ne 0 ]; then
echo "Rule to 1.1.1.1/32 deleted successfully (OK)"
else
echo "Failed to delete rule to 1.1.1.1/32 (FAIL)"
clean_up
exit 1
fi

exit $ret
22 changes: 22 additions & 0 deletions tests/cases/test_ip_rule_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<rules xmlns="urn:okda:iproute2:ip:rule">
<rule>
<pref>200</pref>
<from>1.1.1.1/32</from>
<to>0.0.0.0/0</to>
<tos>default</tos>
<fwmark>0x00</fwmark>
<action>
<table>10</table>
</action>
</rule>
<rule>
<pref>201</pref>
<from>0.0.0.0/0</from>
<to>1.1.1.1/32</to>
<tos>default</tos>
<fwmark>0x00</fwmark>
<action>
<table>20</table>
</action>
</rule>
</rules>
7 changes: 6 additions & 1 deletion yang/iproute2-cmdgen-extensions.yang
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,16 @@ module iproute2-cmdgen-extensions {
on update cmd";
argument "args-names";
}
extension replace-on-update{
extension include-all-on-update{
description
"instruct iproute2 to get all leafs in sysrepo, compare it with the changed leaf, and apply the diff.
typically used where iproute2 cmd require a replace for update, example tc filter, and ip nexthop group";
}
extension replace-on-update{
description
"instruct iproute2 to delete the node and recreate it, example ip rule where no update argument, you have to
recreate the rule";
}
extension include-all-on-delete {
description
"instruct iproute2 to include all leafs on delete";
Expand Down
25 changes: 18 additions & 7 deletions yang/iproute2-ip-link.yang
Original file line number Diff line number Diff line change
Expand Up @@ -114,21 +114,33 @@ module iproute2-ip-link {
"This type is used by data models that need to reference gre
interfaces.";
}
typedef bond-ref {
type leafref {
path "/iplink:links/iplink:bond/iplink:name";
}
description
"This type is used by data models that need to reference bond
interfaces.";
}
typedef l3-links-ref {
type union{
type link-ref;
type bond-ref;
type vti-ref;
type gre-ref;
type vlan-ref;
}
}
typedef bond-ref {
type leafref {
path "/iplink:links/iplink:bond/iplink:name";
typedef all-links-ref {
type union{
type link-ref;
type bond-ref;
type vti-ref;
type gre-ref;
type bridge-ref;
type vrf-ref;
type vlan-ref;
}
description
"This type is used by data models that need to reference bond
interfaces.";
}

/*
Expand Down Expand Up @@ -265,7 +277,6 @@ module iproute2-ip-link {
"loopback device.";
}


/*
* groupings
*/
Expand Down
1 change: 1 addition & 0 deletions yang/iproute2-ip-nexthop.yang
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module iproute2-ip-nexthop {
ipr2cgen:cmd-add "ip nexthop add";
ipr2cgen:cmd-update "ip nexthop replace";
ipr2cgen:cmd-delete "ip nexthop del";
ipr2cgen:include-all-on-update;
key "id";
description
"nexthop configuraton";
Expand Down
2 changes: 1 addition & 1 deletion yang/iproute2-ip-route.yang
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module iproute2-ip-route {
ipr2cgen:cmd-update "ip route replace";
ipr2cgen:cmd-delete "ip route del";
ipr2cgen:cmd-start;
ipr2cgen:replace-on-update;
ipr2cgen:include-all-on-update;
ipr2cgen:oper-cmd "ip route list table all";
// TODO IPv6 support: oper needs to also apply "ip -6 route show"
description
Expand Down
Loading

0 comments on commit 49db039

Please sign in to comment.