summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2015-06-24 13:02:37 +0200
committerSteven Barth <steven@midlink.org>2015-06-24 13:02:37 +0200
commit5b29ffda0099c3bcb8d17a728e1e89dc21a2e68d (patch)
treeddfdd742a3623aae056f7d69f9d59b5c94376965
parent5cf30b59baa03db2448570c78e7e92873555d2ec (diff)
downloadnetifd-5b29ffda0099c3bcb8d17a728e1e89dc21a2e68d.tar.gz
Add mtu6 option to override IPv6 MTU
Signed-off-by: Steven Barth <steven@midlink.org>
-rw-r--r--bridge.c2
-rw-r--r--device.c9
-rw-r--r--device.h3
-rw-r--r--interface-ip.c9
-rw-r--r--system-linux.c28
5 files changed, 35 insertions, 16 deletions
diff --git a/bridge.c b/bridge.c
index 9da5314..4a0cbe9 100644
--- a/bridge.c
+++ b/bridge.c
@@ -299,7 +299,7 @@ bridge_member_cb(struct device_user *dev, enum device_event ev)
* bridge mtu is set
*/
system_if_apply_settings(&bst->dev, &bst->dev.settings,
- DEV_OPT_MTU);
+ DEV_OPT_MTU | DEV_OPT_MTU6);
}
break;
diff --git a/device.c b/device.c
index dd2823d..1265c86 100644
--- a/device.c
+++ b/device.c
@@ -34,6 +34,7 @@ static bool default_ps = true;
static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
[DEV_ATTR_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
[DEV_ATTR_MTU] = { .name = "mtu", .type = BLOBMSG_TYPE_INT32 },
+ [DEV_ATTR_MTU6] = { .name = "mtu6", .type = BLOBMSG_TYPE_INT32 },
[DEV_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING },
[DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 },
[DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL },
@@ -154,6 +155,7 @@ device_merge_settings(struct device *dev, struct device_settings *n)
memset(n, 0, sizeof(*n));
n->mtu = s->flags & DEV_OPT_MTU ? s->mtu : os->mtu;
+ n->mtu6 = s->flags & DEV_OPT_MTU6 ? s->mtu6 : os->mtu6;
n->txqueuelen = s->flags & DEV_OPT_TXQUEUELEN ?
s->txqueuelen : os->txqueuelen;
memcpy(n->macaddr,
@@ -189,6 +191,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
s->flags |= DEV_OPT_MTU;
}
+ if ((cur = tb[DEV_ATTR_MTU6])) {
+ s->mtu6 = blobmsg_get_u32(cur);
+ s->flags |= DEV_OPT_MTU6;
+ }
+
if ((cur = tb[DEV_ATTR_TXQUEUELEN])) {
s->txqueuelen = blobmsg_get_u32(cur);
s->flags |= DEV_OPT_TXQUEUELEN;
@@ -843,6 +850,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
device_merge_settings(dev, &st);
if (st.flags & DEV_OPT_MTU)
blobmsg_add_u32(b, "mtu", st.mtu);
+ if (st.flags & DEV_OPT_MTU6)
+ blobmsg_add_u32(b, "mtu6", st.mtu6);
if (st.flags & DEV_OPT_MACADDR)
blobmsg_add_string(b, "macaddr", format_macaddr(st.macaddr));
if (st.flags & DEV_OPT_TXQUEUELEN)
diff --git a/device.h b/device.h
index 3001f10..4d84d80 100644
--- a/device.h
+++ b/device.h
@@ -28,6 +28,7 @@ typedef int (*device_state_cb)(struct device *, bool up);
enum {
DEV_ATTR_TYPE,
DEV_ATTR_MTU,
+ DEV_ATTR_MTU6,
DEV_ATTR_MACADDR,
DEV_ATTR_TXQUEUELEN,
DEV_ATTR_ENABLED,
@@ -80,6 +81,7 @@ enum {
DEV_OPT_NEIGHREACHABLETIME = (1 << 9),
DEV_OPT_RPS = (1 << 10),
DEV_OPT_XPS = (1 << 11),
+ DEV_OPT_MTU6 = (1 << 12),
};
/* events broadcasted to all users of a device */
@@ -123,6 +125,7 @@ struct device_user {
struct device_settings {
unsigned int flags;
unsigned int mtu;
+ unsigned int mtu6;
unsigned int txqueuelen;
uint8_t macaddr[6];
bool ipv6;
diff --git a/interface-ip.c b/interface-ip.c
index aec3892..7f8a451 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -767,10 +767,11 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment,
route.metric = iface->metric;
system_add_route(l3_downlink, &route);
- if (uplink && uplink->l3_dev.dev) {
- int mtu = system_update_ipv6_mtu(
- uplink->l3_dev.dev, 0);
- if (mtu > 0)
+ if (uplink && uplink->l3_dev.dev && !(l3_downlink->settings.flags & DEV_OPT_MTU6)) {
+ int mtu = system_update_ipv6_mtu(uplink->l3_dev.dev, 0);
+ int mtu_old = system_update_ipv6_mtu(l3_downlink, 0);
+
+ if (mtu > 0 && mtu_old > mtu)
system_update_ipv6_mtu(l3_downlink, mtu);
}
diff --git a/system-linux.c b/system-linux.c
index 6dc9acd..b44eb76 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -1019,6 +1019,10 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
s->flags |= DEV_OPT_MTU;
}
+ s->mtu6 = system_update_ipv6_mtu(dev, 0);
+ if (s->mtu6 > 0)
+ s->flags |= DEV_OPT_MTU6;
+
if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
s->txqueuelen = ifr.ifr_qlen;
s->flags |= DEV_OPT_TXQUEUELEN;
@@ -1114,6 +1118,9 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
s->flags &= ~DEV_OPT_MTU;
}
+ if (s->flags & DEV_OPT_MTU6 & apply_mask) {
+ system_update_ipv6_mtu(dev, s->mtu6);
+ }
if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
ifr.ifr_qlen = s->txqueuelen;
if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
@@ -2163,19 +2170,18 @@ int system_update_ipv6_mtu(struct device *dev, int mtu)
dev->ifname);
int fd = open(buf, O_RDWR);
- ssize_t len = read(fd, buf, sizeof(buf) - 1);
- if (len < 0)
- goto out;
- buf[len] = 0;
- ret = atoi(buf);
+ if (!mtu) {
+ ssize_t len = read(fd, buf, sizeof(buf) - 1);
+ if (len < 0)
+ goto out;
- if (!mtu || ret <= mtu)
- goto out;
-
- lseek(fd, 0, SEEK_SET);
- if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
- ret = -1;
+ buf[len] = 0;
+ ret = atoi(buf);
+ } else {
+ if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
+ ret = mtu;
+ }
out:
close(fd);