From 2ebfc67caed6dbb0d3ebc85f7116faf76cf678f5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 13 Oct 2013 17:29:25 +0200 Subject: Allow changing the MTU --- fastd.c | 41 ++++++++++++++++++++++++++++++++--------- fastd.h | 8 +++++--- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/fastd.c b/fastd.c index 7373e86..1ce476f 100644 --- a/fastd.c +++ b/fastd.c @@ -60,11 +60,12 @@ #include "fastd.h" -#define FASTD_HEADROOM \ +#define FASTD_HDRLEN \ (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct udphdr) + 24) #define FASTD_DEFAULT_MTU 1500 #define FASTD_MIN_MTU 68 +#define FASTD_MAX_MTU 65535 static LIST_HEAD(fastd_list); @@ -126,10 +127,23 @@ static struct notifier_block nl_notifier = { }; + +static int fastd_ndo_change_mtu(struct net_device *dev, int mtu) +{ + if (mtu < FASTD_MIN_MTU || mtu > (FASTD_MAX_MTU-dev->hard_header_len)) + return -EINVAL; + + dev->mtu = mtu; + return 0; +} + + static const struct net_device_ops fastd_netdev_ops_eth = { + .ndo_change_mtu = fastd_ndo_change_mtu, }; static const struct net_device_ops fastd_netdev_ops_ip = { + .ndo_change_mtu = fastd_ndo_change_mtu, }; @@ -163,7 +177,8 @@ static const struct ethtool_ops fastd_ethtool_ops = { }; -static void fastd_netdev_free(struct net_device *dev) { +static void fastd_netdev_free(struct net_device *dev) +{ struct fastd_struct *fastd = netdev_priv(dev); put_net(fastd->net); @@ -178,6 +193,17 @@ static void fastd_netdev_setup(struct net_device *dev) dev->destructor = fastd_netdev_free; } +static inline u16 fastd_header_len(u16 mode) +{ + switch (mode) { + case FASTD_MODE_ETH: + return FASTD_HDRLEN + ETH_HLEN; + + default: + return FASTD_HDRLEN; + } +} + static void fastd_netdev_init(struct net_device *dev) { struct fastd_struct *fastd = netdev_priv(dev); @@ -189,19 +215,17 @@ static void fastd_netdev_init(struct net_device *dev) eth_hw_addr_random(dev); ether_setup(dev); - dev->hard_header_len = FASTD_HEADROOM + ETH_HLEN; - break; case FASTD_MODE_IP: - dev->netdev_ops = &fastd_netdev_ops_eth; + dev->netdev_ops = &fastd_netdev_ops_ip; dev->addr_len = 0; - dev->hard_header_len = FASTD_HEADROOM; - dev->type = ARPHRD_NONE; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; } + + dev->hard_header_len = fastd_header_len(fastd->mode); } static void fastd_destroy_work(struct work_struct *work) @@ -240,10 +264,9 @@ static int fastd_cmd_create(struct sk_buff *skb, struct genl_info *info) if (info->attrs[FASTD_A_MTU]) mtu = nla_get_u16(info->attrs[FASTD_A_MTU]); - if (mtu < FASTD_MIN_MTU) + if (mtu < FASTD_MIN_MTU || mtu > (FASTD_MAX_MTU-fastd_header_len(mode))) return -EINVAL; - if (info->attrs[FASTD_A_IFNAME]) name = nla_data(info->attrs[FASTD_A_IFNAME]); diff --git a/fastd.h b/fastd.h index 5c3ca86..8b89130 100644 --- a/fastd.h +++ b/fastd.h @@ -39,9 +39,11 @@ #ifndef __LINUX_FASTD_H #define __LINUX_FASTD_H -#define FASTD_MODE_ETH 0x0001 -#define FASTD_MODE_IP 0x0002 - +enum { + FASTD_MODE_UNSPEC, + FASTD_MODE_ETH, + FASTD_MODE_IP +}; enum { FASTD_CMD_UNSPEC, -- cgit v1.2.3