1aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/*
2aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * tc_core.c		TC core library.
3aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
4aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		This program is free software; you can redistribute it and/or
5aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		modify it under the terms of the GNU General Public License
6aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		as published by the Free Software Foundation; either version
7aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		2 of the License, or (at your option) any later version.
8aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
9aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
11aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger */
12aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
13aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdio.h>
14aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdlib.h>
15aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <unistd.h>
16aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <syslog.h>
17aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <fcntl.h>
18aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <math.h>
19aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <sys/socket.h>
20aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <netinet/in.h>
21aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <arpa/inet.h>
22aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <string.h>
23aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
24aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include "tc_core.h"
25292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer#include <linux/atm.h>
26aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
27aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic double tick_in_usec = 1;
28147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardystatic double clock_factor = 1;
29aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
3064e2ad593b7610d547741aa3d68b5f130c0560b0Andreas Henrikssonint tc_core_time2big(unsigned time)
31fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger{
328f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	__u64 t = time;
33fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger
34fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger	t *= tick_in_usec;
35fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger	return (t >> 32) != 0;
36fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger}
37fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger
38fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger
39447598449817fcaea26016d9102d703c4d16bd9cAndreas Henrikssonunsigned tc_core_time2tick(unsigned time)
40aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
418f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	return time*tick_in_usec;
42aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
43aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
44447598449817fcaea26016d9102d703c4d16bd9cAndreas Henrikssonunsigned tc_core_tick2time(unsigned tick)
45aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
46aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	return tick/tick_in_usec;
47aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
48aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
4957a800d45a5f8f46c9ce4950599f17545413c82dAndreas Henrikssonunsigned tc_core_time2ktime(unsigned time)
50f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy{
51147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	return time * clock_factor;
52f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy}
53f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy
5457a800d45a5f8f46c9ce4950599f17545413c82dAndreas Henrikssonunsigned tc_core_ktime2time(unsigned ktime)
55f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy{
56147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	return ktime / clock_factor;
57f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy}
58f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy
59aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerunsigned tc_calc_xmittime(unsigned rate, unsigned size)
60aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
618f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	return tc_core_time2tick(TIME_UNITS_PER_SEC*((double)size/rate));
62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
6476dc0aa28fe6fa78e263bf0250c1e42c584dd544Patrick McHardyunsigned tc_calc_xmitsize(unsigned rate, unsigned ticks)
6576dc0aa28fe6fa78e263bf0250c1e42c584dd544Patrick McHardy{
668f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	return ((double)rate*tc_core_tick2time(ticks))/TIME_UNITS_PER_SEC;
6776dc0aa28fe6fa78e263bf0250c1e42c584dd544Patrick McHardy}
6876dc0aa28fe6fa78e263bf0250c1e42c584dd544Patrick McHardy
69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/*
70292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * The align to ATM cells is used for determining the (ATM) SAR
71292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * alignment overhead at the ATM layer. (SAR = Segmentation And
72292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * Reassembly).  This is for example needed when scheduling packet on
73292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * an ADSL connection.  Note that the extra ATM-AAL overhead is _not_
74292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * included in this calculation. This overhead is added in the kernel
75292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * before doing the rate table lookup, as this gives better precision
76292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer * (as the table will always be aligned for 48 bytes).
77292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer *  --Hawk, d.7/11-2004. <hawk@diku.dk>
78292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer */
79292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouerunsigned tc_align_to_atm(unsigned size)
80292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer{
81292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	int linksize, cells;
82292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	cells = size / ATM_CELL_PAYLOAD;
83292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	if ((size % ATM_CELL_PAYLOAD) > 0)
84292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		cells++;
85292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer
86292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	linksize = cells * ATM_CELL_SIZE; /* Use full cell size to add ATM tax */
87292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	return linksize;
88292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer}
89292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer
90839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnaunsigned tc_adjust_size(unsigned sz, unsigned mpu, enum link_layer linklayer)
91839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
92839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (sz < mpu)
93839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		sz = mpu;
94839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
95839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	switch (linklayer) {
96839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	case LINKLAYER_ATM:
97839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return tc_align_to_atm(sz);
98839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	case LINKLAYER_ETHERNET:
99839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	default:
100839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		// No size adjustments on Ethernet
101839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return sz;
102839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
103839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
104839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
105292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer/*
106aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger   rtab[pkt_len>>cell_log] = pkt_xmit_time
107aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger */
108aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
109292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouerint tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
110292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		   int cell_log, unsigned mtu,
111292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		   enum link_layer linklayer)
112aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
113aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	int i;
114839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	unsigned sz;
115d5f46f9cc3856af532e852ef29fd7ddfd141faf0Jesper Dangaard Brouer	unsigned bps = r->rate;
116d5f46f9cc3856af532e852ef29fd7ddfd141faf0Jesper Dangaard Brouer	unsigned mpu = r->mpu;
117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	if (mtu == 0)
119aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger		mtu = 2047;
120aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	if (cell_log < 0) {
122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger		cell_log = 0;
123292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		while ((mtu >> cell_log) > 255)
124aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger			cell_log++;
125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	}
126292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer
127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	for (i=0; i<256; i++) {
128839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		sz = tc_adjust_size((i + 1) << cell_log, mpu, linklayer);
129476daa7278aaf324f6cef27981f81187afce8836Patrick McHardy		rtab[i] = tc_calc_xmittime(bps, sz);
130aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	}
131292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer
132eeee367d91c4004c9f75749b5b09e21fa9244b51Jesper Dangaard Brouer	r->cell_align=-1; // Due to the sz calc
133d5f46f9cc3856af532e852ef29fd7ddfd141faf0Jesper Dangaard Brouer	r->cell_log=cell_log;
134aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	return cell_log;
135aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
136aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
137839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna/*
138839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna   stab[pkt_len>>cell_log] = pkt_xmit_size>>size_log
139839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna */
140839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
141839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnaint tc_calc_size_table(struct tc_sizespec *s, __u16 **stab)
142839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
143839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	int i;
144839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	enum link_layer linklayer = s->linklayer;
145839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	unsigned int sz;
146839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
147839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (linklayer <= LINKLAYER_ETHERNET && s->mpu == 0) {
148839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		/* don't need data table in this case (only overhead set) */
149839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->mtu = 0;
150839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->tsize = 0;
151839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->cell_log = 0;
152839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->cell_align = 0;
153839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		*stab = NULL;
154839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return 0;
155839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
156839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
157839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (s->mtu == 0)
158839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->mtu = 2047;
159839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (s->tsize == 0)
160839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->tsize = 512;
161839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
162839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	s->cell_log = 0;
163839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	while ((s->mtu >> s->cell_log) > s->tsize - 1)
164839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		s->cell_log++;
165839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
166839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	*stab = malloc(s->tsize * sizeof(__u16));
167839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (!*stab)
168839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return -1;
169839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
170839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnaagain:
171839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	for (i = s->tsize - 1; i >= 0; i--) {
172839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		sz = tc_adjust_size((i + 1) << s->cell_log, s->mpu, linklayer);
173839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if ((sz >> s->size_log) > UINT16_MAX) {
174839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			s->size_log++;
175839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			goto again;
176839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		}
177839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		(*stab)[i] = sz >> s->size_log;
178839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
179839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
180839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	s->cell_align = -1; // Due to the sz calc
181839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	return 0;
182839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
183839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
184aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerint tc_core_init()
185aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
186147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	FILE *fp;
187147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	__u32 clock_res;
188147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	__u32 t2us;
189147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	__u32 us2t;
190aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
191147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	fp = fopen("/proc/net/psched", "r");
192aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	if (fp == NULL)
193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger		return -1;
194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
195147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	if (fscanf(fp, "%08x%08x%08x", &t2us, &us2t, &clock_res) != 3) {
196aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger		fclose(fp);
197aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger		return -1;
198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	}
199aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	fclose(fp);
200147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy
201147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	/* compatibility hack: for old iproute binaries (ignoring
202147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	 * the kernel clock resolution) the kernel advertises a
203147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	 * tick multiplier of 1000 in case of nano-second resolution,
204147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	 * which really is 1. */
205147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	if (clock_res == 1000000000)
206147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy		t2us = us2t;
207147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy
208147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	clock_factor  = (double)clock_res / TIME_UNITS_PER_SEC;
209147e1d4b5abad8da3fc69fb23a4c9a4457e65d66Patrick McHardy	tick_in_usec = (double)t2us / us2t * clock_factor;
210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger	return 0;
211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
212