North American Network Operators Group

Date Prev | Date Next | Date Index | Thread Index | Author Index | Historical

Re: MTU path discovery and IPSec

  • From: Barney Wolff
  • Date: Wed Dec 10 16:08:26 2003

On Wed, Dec 10, 2003 at 03:43:59PM -0500, Joe Maimon wrote:
> 
> Packets are fragmented into equally sized units to prevent further 
> downstream fragmentation.

For amusement's sake, in response to a challenge from Crist Clark,
here's code to do it right.  Pretty simple, although I have no idea
how to do it in an ASIC.

-- 
Barney Wolff         http://www.databus.com/bwresume.pdf
I'm available by contract or FT, in the NYC metro area or via the 'Net.
//	Simulate a fragmentation algorithm
//	frag Omtu [Ihdrsz]
//	Barney Wolff	<[email protected]>	12/4/03
//	Copyright (c) Databus Inc.  Free to use with attribution.

#include <iostream>
#include <cstdlib>
using namespace std;

int
main(int argc, char **argv) {
	int	Ihdrsz=20, Omtu, MinIpaysz, MaxIpaysz, Opaylst, Opaysz;
	switch (argc) {
	default:	cerr << "Usage: frag-alg Omtu [Ihdrsz]\n"; exit(1);
	case 3:		Ihdrsz = atoi(argv[2]);
	case 2:		Omtu = atoi(argv[1]);
	}

	MinIpaysz = Omtu - 1 - Ihdrsz;
	MaxIpaysz = 65535 - Ihdrsz;
	Opaylst = Omtu - Ihdrsz;
	Opaysz = Opaylst & 0xfff8;
	cout << "Output MTU " << Omtu << " Input header size " << Ihdrsz << endl;
	cout << "Max payload of last packet: "<<Opaylst<<" others "<<Opaysz<<endl;

	for (int Ipaysz=MinIpaysz; Ipaysz<=MaxIpaysz; Ipaysz++) {
		cout << Ipaysz + Ihdrsz;
		int Opayn = Opaysz, Nfrag, Maxin, Lastsz, Delta;
		Nfrag = 1 + (Ipaysz - Opaylst + Opaysz - 1) / Opaysz;
		Maxin = Nfrag * Opaysz;
		if (Maxin > Ipaysz) Opayn -= ((Maxin - Ipaysz) / Nfrag) & 0xfff8;
		Lastsz = Ipaysz - (Nfrag-1) * Opayn;
		Delta = Opayn - Lastsz;
		if (Delta >= 8) {
			int Nfrag2 = Delta / 8;
			Nfrag -= Nfrag2;
			Lastsz += 8 * Nfrag2;
			cout << " " << Nfrag2 << " " << Opayn-8+Ihdrsz;
		}
		if (Nfrag > 1) cout << " " << Nfrag-1 << " " << Opayn+Ihdrsz;
		cout << " " << Lastsz+Ihdrsz;
		if (Lastsz-Opayn>8 || Opayn-Lastsz>8) cout << " *";
		cout << endl;
	}
	exit(0);
}