Skip to content

Commit

Permalink
Add support for setting and fetching IPv4/IPv6 interface MTU
Browse files Browse the repository at this point in the history
Setting the link MTU in Linux changes the sysctl IPV6 MTU, so we have to
set the IPv6 MTU on each run in case the IPv4 MTU changes.  Hence, this
also means the IPv6 MTU must be set *after* the IPv4 (link) MTU.

statd has been updated to read the sysctl setting for IPv6 MTU.

Notice how the loopback interface is unsupported for config + status.

Fixes issue #151

Signed-off-by: Joachim Wiberg <[email protected]>
  • Loading branch information
troglobit committed Oct 2, 2023
1 parent f9d5586 commit fa5548b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 28 deletions.
65 changes: 51 additions & 14 deletions src/confd/src/ietf-interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,22 @@ static int netdag_set_conf_addrs(FILE *ip, const char *ifname,
return 0;
}

static int netdag_gen_link_mtu(FILE *ip, struct lyd_node *dif)
{
const char *ifname = lydx_get_cattr(dif, "name");
struct lyd_node *node;
struct lydx_diff nd;

if (!strcmp(ifname, "lo")) /* skip for now */
return 0;

node = lydx_get_descendant(lyd_child(dif), "ipv4", "mtu", NULL);
if (node && lydx_get_diff(node, &nd))
fprintf(ip, "link set %s mtu %s\n", ifname, nd.new ? nd.val : "1500");

return 0;
}

static int netdag_gen_link_addr(FILE *ip, struct lyd_node *cif, struct lyd_node *dif)
{
const char *ifname = lydx_get_cattr(dif, "name");
Expand Down Expand Up @@ -570,12 +586,12 @@ static int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
return err;
}

static int netdag_gen_sysctl_bool(struct dagger *net,
const char *ifname, FILE **fpp,
struct lyd_node *node,
const char *fmt, ...)
static int netdag_gen_sysctl_setting(struct dagger *net, const char *ifname, FILE **fpp,
int isboolean, const char *fallback,
struct lyd_node *node, const char *fmt, ...)
{
struct lydx_diff nd;
const char *value;
va_list ap;

if (!node)
Expand All @@ -584,18 +600,32 @@ static int netdag_gen_sysctl_bool(struct dagger *net,
if (!lydx_get_diff(node, &nd))
return 0;

*fpp = *fpp ? : dagger_fopen_next(net, "init", ifname,
60, "init.sysctl");
*fpp = *fpp ? : dagger_fopen_next(net, "init", ifname, 60, "init.sysctl");
if (!*fpp)
return -EIO;

va_start(ap, fmt);
vfprintf(*fpp, fmt, ap);
va_end(ap);
fprintf(*fpp, " = %u\n", (nd.new && !strcmp(nd.val, "true")) ? 1 : 0);

if (isboolean) {
if (nd.new && !strcmp(nd.val, "true"))
value = "1";
else
value = "0";
} else {
if (nd.new)
value = nd.val;
else
value = fallback;
}

fprintf(*fpp, " = %s\n", value);

return 0;
}
static int netdag_gen_sysctl(struct dagger *net,
struct lyd_node *cif,
struct lyd_node *dif)
{
const char *ifname = lydx_get_cattr(dif, "name");
Expand All @@ -604,15 +634,21 @@ static int netdag_gen_sysctl(struct dagger *net,
int err = 0;

node = lydx_get_descendant(lyd_child(dif), "ipv4", "forwarding", NULL);
err = err ? : netdag_gen_sysctl_bool(net, ifname, &sysctl, node,
"net.ipv4.conf.%s.forwarding",
ifname);
err = err ? : netdag_gen_sysctl_setting(net, ifname, &sysctl, 1, "0", node,
"net.ipv4.conf.%s.forwarding", ifname);

node = lydx_get_descendant(lyd_child(dif), "ipv6", "forwarding", NULL);
err = err ? : netdag_gen_sysctl_bool(net, ifname, &sysctl, node,
"net.ipv6.conf.%s.forwarding",
ifname);
err = err ? : netdag_gen_sysctl_setting(net, ifname, &sysctl, 1, "0", node,
"net.ipv6.conf.%s.forwarding", ifname);

if (!strcmp(ifname, "lo")) /* skip for now */
goto skip_mtu;

node = lydx_get_descendant(lyd_child(cif), "ipv6", "mtu", NULL);
err = err ? : netdag_gen_sysctl_setting(net, ifname, &sysctl, 0, "1280", node,
"net.ipv6.conf.%s.mtu", ifname);

skip_mtu:
if (sysctl)
fclose(sysctl);

Expand Down Expand Up @@ -1093,6 +1129,7 @@ static sr_error_t netdag_gen_iface(struct dagger *net,
}

/* Set Addresses */
err = err ? : netdag_gen_link_mtu(ip, dif);
err = err ? : netdag_gen_link_addr(ip, cif, dif);
err = err ? : netdag_gen_ip_addrs(ip, "ipv4", cif, dif);
err = err ? : netdag_gen_ip_addrs(ip, "ipv6", cif, dif);
Expand All @@ -1104,7 +1141,7 @@ static sr_error_t netdag_gen_iface(struct dagger *net,
if (!attr || !strcmp(attr, "true"))
fprintf(ip, "link set dev %s up state up\n", ifname);

err = err ? : netdag_gen_sysctl(net, dif);
err = err ? : netdag_gen_sysctl(net, cif, dif);

err_close_ip:
fclose(ip);
Expand Down
8 changes: 0 additions & 8 deletions src/confd/yang/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ module infix-ip {
}
}

deviation "/if:interfaces/if:interface/ip:ipv4/ip:mtu" {
deviate not-supported;
}

deviation "/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask" {
deviate not-supported;
}
Expand All @@ -62,10 +58,6 @@ module infix-ip {
deviate not-supported;
}

deviation "/if:interfaces/if:interface/ip:ipv6/ip:mtu" {
deviate not-supported;
}

deviation "/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status" {
deviate not-supported;
}
Expand Down
21 changes: 15 additions & 6 deletions src/statd/iface-ip-addr.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
Expand Down Expand Up @@ -47,6 +48,7 @@ static const char *get_yang_origin(const char *protocol)
static int ly_add_ip_mtu(const struct ly_ctx *ctx, struct lyd_node *node,
char *xpath, json_t *j_iface, char *ifname)
{
json_int_t j_mtu;
json_t *j_val;
int err;

Expand All @@ -57,14 +59,21 @@ static int ly_add_ip_mtu(const struct ly_ctx *ctx, struct lyd_node *node,
if (strcmp(ifname, "lo") == 0)
return SR_ERR_OK;

j_val = json_object_get(j_iface, "mtu");
if (!json_is_integer(j_val)) {
ERROR("Expected a JSON integer for 'mtu'");
return SR_ERR_SYS;
if (strstr(xpath, "ipv4")) {
j_val = json_object_get(j_iface, "mtu");
if (!json_is_integer(j_val)) {
ERROR("Expected a JSON integer for 'mtu'");
return SR_ERR_SYS;
}
j_mtu = json_integer_value(j_val);
} else {
if (readllf(&j_mtu, "/proc/sys/net/ipv6/conf/%s/mtu", ifname)) {
ERROR("Failed reading sysctl value of %s IPv6 MTU: %s", ifname, strerror(errno));
return SR_ERR_SYS;
}
}

err = lydx_new_path(ctx, &node, xpath, "mtu", "%lld",
json_integer_value(j_val));
err = lydx_new_path(ctx, &node, xpath, "mtu", "%lld", j_mtu);
if (err) {
ERROR("Error, adding 'mtu' to data tree, libyang error %d", err);
return SR_ERR_LY;
Expand Down

0 comments on commit fa5548b

Please sign in to comment.