Skip to content

Commit

Permalink
add 'iif' key to routing-policy entry
Browse files Browse the repository at this point in the history
It's now possible to specify the incoming interface for a routing
policy entry.

Example:

  network:
    version: 2
    ethernets:
      if0: {}
      eth0:
        dhcp4: true
        routing-policy:
          - table: 101
            iif: if0

Signed-off-by: Emanuele Altomare <emanuele@common-net.org>
  • Loading branch information
aldobrrrr committed Feb 21, 2025
1 parent 52ea6f3 commit 67439d7
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 3 deletions.
4 changes: 4 additions & 0 deletions doc/netplan-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,10 @@ network:

> Match on traffic going to the specified destination.

- **`iif`** (scalar)

> Set an incoming interface to match traffic for this policy rule.

- **`table`** (scalar)

> The table number to match for the route. In some scenarios, it may be
Expand Down
1 change: 1 addition & 0 deletions src/netplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ write_routes(yaml_event_t* event, yaml_emitter_t* emitter, const NetplanNetDefin
YAML_UINT_DEFAULT(def, event, emitter, "mark", r->fwmark, NETPLAN_IP_RULE_FW_MARK_UNSPEC);
YAML_STRING(def, event, emitter, "from", r->from);
YAML_STRING(def, event, emitter, "to", r->to);
YAML_STRING(def, event, emitter, "iif", r->iif);
YAML_MAPPING_CLOSE(event, emitter);
}
YAML_SEQUENCE_CLOSE(event, emitter);
Expand Down
3 changes: 3 additions & 0 deletions src/networkd.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,9 @@ write_ip_rule(NetplanIPRule* r, GString* s)
g_string_append_printf(s, "From=%s\n", r->from);
if (r->to)
g_string_append_printf(s, "To=%s\n", r->to);
if (r->iif)
g_string_append_printf(s, "IncomingInterface=%s\n", r->iif);


if (r->table != NETPLAN_ROUTE_TABLE_UNSPEC)
g_string_append_printf(s, "Table=%d\n", r->table);
Expand Down
2 changes: 2 additions & 0 deletions src/nm.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ write_ip_rules_nm(const NetplanNetDefinition* def, GKeyFile *kf, gint family, GE
g_string_append_printf(tmp_val, " from %s", cur_rule->from);
if (cur_rule->to)
g_string_append_printf(tmp_val, " to %s", cur_rule->to);
if (cur_rule->iif)
g_string_append_printf(tmp_val, " iif %s", cur_rule->iif);
if (cur_rule->tos != NETPLAN_IP_RULE_TOS_UNSPEC)
g_string_append_printf(tmp_val, " tos %u", cur_rule->tos);
if (cur_rule->fwmark != NETPLAN_IP_RULE_FW_MARK_UNSPEC)
Expand Down
27 changes: 25 additions & 2 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,21 @@ handle_generic_str(NetplanParser* npp, yaml_node_t* node, void* entryptr, const
return TRUE;
}

/**
* Handler for setting a string ID field from a scalar node, inside a given struct
* @entryptr: pointer to the beginning of the to-be-modified data structure
* @data: offset into entryptr struct where the const char* field to write is
* located
*/
STATIC gboolean
handle_generic_id(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
if (!assert_valid_id(npp, node, error))
return FALSE;

return handle_generic_str(npp, node, entryptr, data, error);
}

STATIC gboolean
handle_special_macaddress_option(NetplanParser* npp, yaml_node_t* node, void* entryptr, const void* data, GError** error)
{
Expand Down Expand Up @@ -2048,6 +2063,12 @@ handle_ip_rule_ip(NetplanParser* npp, yaml_node_t* node, const void* data, GErro
return TRUE;
}

STATIC gboolean
handle_ip_rule_iif(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
return handle_generic_id(npp, node, npp->current.ip_rule, (void *) data, error);
}

STATIC gboolean
handle_ip_rule_guint(NetplanParser* npp, yaml_node_t* node, const void* data, GError** error)
{
Expand Down Expand Up @@ -2295,6 +2316,7 @@ static const mapping_entry_handler ip_rules_handlers[] = {
{"table", YAML_SCALAR_NODE, {.generic=handle_ip_rule_guint}, ip_rule_offset(table)},
{"to", YAML_SCALAR_NODE, {.generic=handle_ip_rule_ip}, ip_rule_offset(to)},
{"type-of-service", YAML_SCALAR_NODE, {.generic=handle_ip_rule_tos}, ip_rule_offset(tos)},
{"iif", YAML_SCALAR_NODE, {.generic=handle_ip_rule_iif}, ip_rule_offset(iif)},
{NULL}
};

Expand All @@ -2309,11 +2331,12 @@ handle_ip_rules(NetplanParser* npp, yaml_node_t* node, __unused const void* _, G
reset_ip_rule(ip_rule);

npp->current.ip_rule = ip_rule;

ret = process_mapping(npp, entry, NULL, ip_rules_handlers, NULL, error);
npp->current.ip_rule = NULL;

if (ret && !ip_rule->from && !ip_rule->to)
ret = yaml_error(npp, node, error, "IP routing policy must include either a 'from' or 'to' IP");
if (ret && !ip_rule->from && !ip_rule->to && !ip_rule->iif)
ret = yaml_error(npp, node, error, "IP routing policy must include at least one of the following fields: 'from', 'to', 'iif'");

if (!ret) {
ip_rule_clear(&ip_rule);
Expand Down
3 changes: 3 additions & 0 deletions src/types-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ typedef struct {
guint fwmark;
/* type-of-service: between 0 and 255 */
guint tos;

/* incoming interface */
char* iif;
} NetplanIPRule;

struct netplan_vxlan {
Expand Down
1 change: 1 addition & 0 deletions src/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ free_ip_rules(void* ptr)
NetplanIPRule* rule = ptr;
g_free(rule->to);
g_free(rule->from);
g_free(rule->iif);
g_free(rule);
}

Expand Down
3 changes: 2 additions & 1 deletion src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,8 @@ is_route_rule_present(const NetplanNetDefinition* netdef, const NetplanIPRule* r
entry->table == rule->table &&
entry->priority == rule->priority &&
entry->fwmark == rule->fwmark &&
entry->tos == rule->tos
entry->tos == rule->tos &&
g_strcmp0(entry->iif, rule->iif) == 0
)
return TRUE;
}
Expand Down
12 changes: 12 additions & 0 deletions tests/generator/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,18 @@ def test_device_ip_rule_invalid_address(self):
- 192.168.14.2/24
- 2001:FFfe::1/64''', expect_fail=True)

def test_device_ip_rule_invalid_iif(self):
self.generate('''network:
version: 2
ethernets:
engreen:
routing-policy:
- from: 10.10.10.0/24
iif: not valid iface name
addresses:
- 192.168.14.2/24
- 2001:FFfe::1/64''', expect_fail=True)

def test_invalid_dhcp_identifier(self):
self.generate('''network:
version: 2
Expand Down
56 changes: 56 additions & 0 deletions tests/generator/test_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,31 @@ def test_ip_rule_tos(self):
[RoutingPolicyRule]
To=10.10.10.0/24
TypeOfService=250
'''})

def test_ip_rule_iif(self):
self.generate('''network:
version: 2
ethernets:
engreen:
addresses: ["192.168.14.2/24"]
routing-policy:
- to: 10.10.10.0/24
table: 100
iif: if0
''')

self.assert_networkd({'engreen.network': '''[Match]
Name=engreen
[Network]
LinkLocalAddressing=ipv6
Address=192.168.14.2/24
[RoutingPolicyRule]
To=10.10.10.0/24
Table=100
IncomingInterface=if0
'''})

def test_use_routes(self):
Expand Down Expand Up @@ -1185,6 +1210,37 @@ def test_ip_rule_tos(self):
address1=192.168.14.2/24
routing-rule1=priority 99 to 10.10.10.0/24 tos 250
[ipv6]
method=ignore
'''})

def test_ip_rule_iif(self):
self.generate('''network:
version: 2
renderer: NetworkManager
ethernets:
engreen:
addresses: ["192.168.14.2/24"]
routing-policy:
- to: 10.10.10.0/24
table: 100
priority: 99
iif: if0
''')

self.assert_nm({'engreen': '''[connection]
id=netplan-engreen
type=ethernet
interface-name=engreen
[ethernet]
wake-on-lan=0
[ipv4]
method=manual
address1=192.168.14.2/24
routing-rule1=priority 99 to 10.10.10.0/24 iif if0 table 100
[ipv6]
method=ignore
'''})
Expand Down

0 comments on commit 67439d7

Please sign in to comment.