This commit is contained in:
tuna2134
2026-07-06 15:03:21 +09:00
parent e2707818dd
commit 20cf4124c8
2 changed files with 57 additions and 2 deletions

View File

@@ -37,6 +37,19 @@ sudo ip link set eip0 up
sudo ip addr add 192.0.2.1/30 dev eip0 sudo ip addr add 192.0.2.1/30 dev eip0
``` ```
MTUを省略した場合、Overlay MTUはUnderlayの経路MTUからIPv6、EtherIP、
Ethernetヘッダーの合計56 byteを差し引いた値に自動調整されます。例えば
Underlay MTUが1500の場合、Overlay MTUは1444になり、通常の送信では外側IPv6
フラグメントを生成しません。
明示的に大きなMTUを設定することもできます。その場合は、カプセル化後の
パケットが実際のUnderlay経路MTUを超えたときだけ送信元でIPv6フラグメントを
生成します。
```sh
sudo ip link set eip0 mtu 1500
```
## トンネルの削除 ## トンネルの削除
```sh ```sh

View File

@@ -32,6 +32,8 @@
#define ETHERIP6_HLEN 2 #define ETHERIP6_HLEN 2
#define ETHERIP6_DEFAULT_HOP_LIMIT 64 #define ETHERIP6_DEFAULT_HOP_LIMIT 64
#define ETHERIP6_MAX_MTU 9000 #define ETHERIP6_MAX_MTU 9000
#define ETHERIP6_ENCAP_HLEN (sizeof(struct ipv6hdr) + ETHERIP6_HLEN)
#define ETHERIP6_MTU_OVERHEAD (ETHERIP6_ENCAP_HLEN + ETH_HLEN)
struct etherip6_tunnel { struct etherip6_tunnel {
struct list_head list; struct list_head list;
@@ -140,6 +142,35 @@ static struct etherip6_tunnel *etherip6_lookup_rx(struct net *net,
return etherip6_lookup_unique_rx(net, local, remote, iif, false, false); return etherip6_lookup_unique_rx(net, local, remote, iif, false, false);
} }
static unsigned int etherip6_underlay_mtu(struct net *net,
const struct etherip6_tunnel *tun)
{
struct dst_entry *dst;
struct flowi6 fl6 = {};
unsigned int mtu = 0;
fl6.flowi6_proto = IPPROTO_ETHERIP;
fl6.flowi6_oif = tun->link;
fl6.daddr = tun->remote;
fl6.saddr = tun->local;
dst = ip6_route_output(net, NULL, &fl6);
if (!dst->error)
mtu = dst_mtu(dst);
dst_release(dst);
return mtu;
}
static unsigned int etherip6_overlay_mtu(unsigned int underlay_mtu)
{
if (underlay_mtu <= ETHERIP6_MTU_OVERHEAD + ETH_MIN_MTU)
return ETH_MIN_MTU;
return min_t(unsigned int, underlay_mtu - ETHERIP6_MTU_OVERHEAD,
ETHERIP6_MAX_MTU);
}
static netdev_tx_t etherip6_xmit(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t etherip6_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct etherip6_tunnel *tun = netdev_priv(dev); struct etherip6_tunnel *tun = netdev_priv(dev);
@@ -191,7 +222,8 @@ static netdev_tx_t etherip6_xmit(struct sk_buff *skb, struct net_device *dev)
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->dev = dst->dev; skb->dev = dst->dev;
skb->ignore_df = 1; /* IPv6 source fragmentation is needed only above the underlay PMTU. */
skb->ignore_df = skb->len > dst_mtu(dst);
skb_dst_set(skb, dst); skb_dst_set(skb, dst);
stats = this_cpu_ptr(tun->stats); stats = this_cpu_ptr(tun->stats);
@@ -252,6 +284,7 @@ static void etherip6_setup(struct net_device *dev)
dev->vlan_features = 0; dev->vlan_features = 0;
dev->min_mtu = ETH_MIN_MTU; dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = ETHERIP6_MAX_MTU; dev->max_mtu = ETHERIP6_MAX_MTU;
dev->needed_headroom = ETHERIP6_ENCAP_HLEN;
eth_hw_addr_random(dev); eth_hw_addr_random(dev);
} }
@@ -318,6 +351,15 @@ static int etherip6_newlink(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
/* Keep the default overlay packets below the current underlay PMTU. */
if (!params->tb[IFLA_MTU]) {
unsigned int underlay_mtu;
underlay_mtu = etherip6_underlay_mtu(dev_net(dev), tun);
if (underlay_mtu)
dev->mtu = etherip6_overlay_mtu(underlay_mtu);
}
tun->dev = dev; tun->dev = dev;
atomic_long_set(&tun->tx_dropped, 0); atomic_long_set(&tun->tx_dropped, 0);
atomic_long_set(&tun->rx_dropped, 0); atomic_long_set(&tun->rx_dropped, 0);