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