Commit 292f29b4 authored by Jesper Dangaard Brouer's avatar Jesper Dangaard Brouer Committed by Stephen Hemminger

ATM cell alignment.

Introducing the function that does the ATM cell alignment, and
modifying tc_calc_rtable() to use this based upon a linklayer
parameter.

Modified from original to use constants from atm.h and
fix all the usages of rtable in same patch.
Signed-off-by: default avatarJesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
parent 1a5bd776
/* atm.h - general ATM declarations */
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
/*
* WARNING: User-space programs should not #include <linux/atm.h> directly.
* Instead, #include <atm.h>
*/
#ifndef _LINUX_ATM_H
#define _LINUX_ATM_H
/*
* BEGIN_xx and END_xx markers are used for automatic generation of
* documentation. Do not change them.
*/
#include <linux/atmapi.h>
#include <linux/atmsap.h>
#include <linux/atmioc.h>
/* general ATM constants */
#define ATM_CELL_SIZE 53 /* ATM cell size incl. header */
#define ATM_CELL_PAYLOAD 48 /* ATM payload size */
#define ATM_AAL0_SDU 52 /* AAL0 SDU size */
#define ATM_MAX_AAL34_PDU 65535 /* maximum AAL3/4 PDU payload */
#define ATM_AAL5_TRAILER 8 /* AAL5 trailer size */
#define ATM_MAX_AAL5_PDU 65535 /* maximum AAL5 PDU payload */
#define ATM_MAX_CDV 9999 /* maximum (default) CDV */
#define ATM_NOT_RSV_VCI 32 /* first non-reserved VCI value */
#define ATM_MAX_VPI 255 /* maximum VPI at the UNI */
#define ATM_MAX_VPI_NNI 4096 /* maximum VPI at the NNI */
#define ATM_MAX_VCI 65535 /* maximum VCI */
/* "protcol" values for the socket system call */
#define ATM_NO_AAL 0 /* AAL not specified */
#define ATM_AAL0 13 /* "raw" ATM cells */
#define ATM_AAL1 1 /* AAL1 (CBR) */
#define ATM_AAL2 2 /* AAL2 (VBR) */
#define ATM_AAL34 3 /* AAL3/4 (data) */
#define ATM_AAL5 5 /* AAL5 (data) */
/*
* socket option name coding functions
*
* Note that __SO_ENCODE and __SO_LEVEL are somewhat a hack since the
* << 22 only reserves 9 bits for the level. On some architectures
* SOL_SOCKET is 0xFFFF, so that's a bit of a problem
*/
#define __SO_ENCODE(l,n,t) ((((l) & 0x1FF) << 22) | ((n) << 16) | \
sizeof(t))
#define __SO_LEVEL_MATCH(c,m) (((c) >> 22) == ((m) & 0x1FF))
#define __SO_NUMBER(c) (((c) >> 16) & 0x3f)
#define __SO_SIZE(c) ((c) & 0x3fff)
/*
* ATM layer
*/
#define SO_SETCLP __SO_ENCODE(SOL_ATM,0,int)
/* set CLP bit value - TODO */
#define SO_CIRANGE __SO_ENCODE(SOL_ATM,1,struct atm_cirange)
/* connection identifier range; socket must be
bound or connected */
#define SO_ATMQOS __SO_ENCODE(SOL_ATM,2,struct atm_qos)
/* Quality of Service setting */
#define SO_ATMSAP __SO_ENCODE(SOL_ATM,3,struct atm_sap)
/* Service Access Point */
#define SO_ATMPVC __SO_ENCODE(SOL_ATM,4,struct sockaddr_atmpvc)
/* "PVC" address (also for SVCs); get only */
#define SO_MULTIPOINT __SO_ENCODE(SOL_ATM, 5, int)
/* make this vc a p2mp */
/*
* Note @@@: since the socket layers don't really distinguish the control and
* the data plane but generally seems to be data plane-centric, any layer is
* about equally wrong for the SAP. If you have a better idea about this,
* please speak up ...
*/
/* ATM cell header (for AAL0) */
/* BEGIN_CH */
#define ATM_HDR_GFC_MASK 0xf0000000
#define ATM_HDR_GFC_SHIFT 28
#define ATM_HDR_VPI_MASK 0x0ff00000
#define ATM_HDR_VPI_SHIFT 20
#define ATM_HDR_VCI_MASK 0x000ffff0
#define ATM_HDR_VCI_SHIFT 4
#define ATM_HDR_PTI_MASK 0x0000000e
#define ATM_HDR_PTI_SHIFT 1
#define ATM_HDR_CLP 0x00000001
/* END_CH */
/* PTI codings */
/* BEGIN_PTI */
#define ATM_PTI_US0 0 /* user data cell, congestion not exp, SDU-type 0 */
#define ATM_PTI_US1 1 /* user data cell, congestion not exp, SDU-type 1 */
#define ATM_PTI_UCES0 2 /* user data cell, cong. experienced, SDU-type 0 */
#define ATM_PTI_UCES1 3 /* user data cell, cong. experienced, SDU-type 1 */
#define ATM_PTI_SEGF5 4 /* segment OAM F5 flow related cell */
#define ATM_PTI_E2EF5 5 /* end-to-end OAM F5 flow related cell */
#define ATM_PTI_RSV_RM 6 /* reserved for traffic control/resource mgmt */
#define ATM_PTI_RSV 7 /* reserved */
/* END_PTI */
/*
* The following items should stay in linux/atm.h, which should be linked to
* netatm/atm.h
*/
/* Traffic description */
#define ATM_NONE 0 /* no traffic */
#define ATM_UBR 1
#define ATM_CBR 2
#define ATM_VBR 3
#define ATM_ABR 4
#define ATM_ANYCLASS 5 /* compatible with everything */
#define ATM_MAX_PCR -1 /* maximum available PCR */
struct atm_trafprm {
unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */
int max_pcr; /* maximum PCR in cells per second */
int pcr; /* desired PCR in cells per second */
int min_pcr; /* minimum PCR in cells per second */
int max_cdv; /* maximum CDV in microseconds */
int max_sdu; /* maximum SDU in bytes */
/* extra params for ABR */
unsigned int icr; /* Initial Cell Rate (24-bit) */
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */
unsigned int frtt : 24; /* Fixed Round Trip Time (24-bit) */
unsigned int rif : 4; /* Rate Increment Factor (4-bit) */
unsigned int rdf : 4; /* Rate Decrease Factor (4-bit) */
unsigned int nrm_pres :1; /* nrm present bit */
unsigned int trm_pres :1; /* rm present bit */
unsigned int adtf_pres :1; /* adtf present bit */
unsigned int cdf_pres :1; /* cdf present bit*/
unsigned int nrm :3; /* Max # of Cells for each forward RM cell (3-bit) */
unsigned int trm :3; /* Time between forward RM cells (3-bit) */
unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */
unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */
unsigned int spare :9; /* spare bits */
};
struct atm_qos {
struct atm_trafprm txtp; /* parameters in TX direction */
struct atm_trafprm rxtp __ATM_API_ALIGN;
/* parameters in RX direction */
unsigned char aal __ATM_API_ALIGN;
};
/* PVC addressing */
#define ATM_ITF_ANY -1 /* "magic" PVC address values */
#define ATM_VPI_ANY -1
#define ATM_VCI_ANY -1
#define ATM_VPI_UNSPEC -2
#define ATM_VCI_UNSPEC -2
struct sockaddr_atmpvc {
unsigned short sap_family; /* address family, AF_ATMPVC */
struct { /* PVC address */
short itf; /* ATM interface */
short vpi; /* VPI (only 8 bits at UNI) */
int vci; /* VCI (only 16 bits at UNI) */
} sap_addr __ATM_API_ALIGN; /* PVC address */
};
/* SVC addressing */
#define ATM_ESA_LEN 20 /* ATM End System Address length */
#define ATM_E164_LEN 12 /* maximum E.164 number length */
#define ATM_AFI_DCC 0x39 /* DCC ATM Format */
#define ATM_AFI_ICD 0x47 /* ICD ATM Format */
#define ATM_AFI_E164 0x45 /* E.164 ATM Format */
#define ATM_AFI_LOCAL 0x49 /* Local ATM Format */
#define ATM_AFI_DCC_GROUP 0xBD /* DCC ATM Group Format */
#define ATM_AFI_ICD_GROUP 0xC5 /* ICD ATM Group Format */
#define ATM_AFI_E164_GROUP 0xC3 /* E.164 ATM Group Format */
#define ATM_AFI_LOCAL_GROUP 0xC7 /* Local ATM Group Format */
#define ATM_LIJ_NONE 0 /* no leaf-initiated join */
#define ATM_LIJ 1 /* request joining */
#define ATM_LIJ_RPJ 2 /* set to root-prompted join */
#define ATM_LIJ_NJ 3 /* set to network join */
struct sockaddr_atmsvc {
unsigned short sas_family; /* address family, AF_ATMSVC */
struct { /* SVC address */
unsigned char prv[ATM_ESA_LEN];/* private ATM address */
char pub[ATM_E164_LEN+1]; /* public address (E.164) */
/* unused addresses must be bzero'ed */
char lij_type; /* role in LIJ call; one of ATM_LIJ* */
uint32_t lij_id; /* LIJ call identifier */
} sas_addr __ATM_API_ALIGN; /* SVC address */
};
static __inline__ int atmsvc_addr_in_use(struct sockaddr_atmsvc addr)
{
return *addr.sas_addr.prv || *addr.sas_addr.pub;
}
static __inline__ int atmpvc_addr_in_use(struct sockaddr_atmpvc addr)
{
return addr.sap_addr.itf || addr.sap_addr.vpi || addr.sap_addr.vci;
}
/*
* Some stuff for linux/sockios.h
*/
struct atmif_sioc {
int number;
int length;
void *arg;
};
typedef unsigned short atm_backend_t;
#endif
/* atmapi.h - ATM API user space/kernel compatibility */
/* Written 1999,2000 by Werner Almesberger, EPFL ICA */
#ifndef _LINUX_ATMAPI_H
#define _LINUX_ATMAPI_H
#if defined(__sparc__) || defined(__ia64__)
/* such alignment is not required on 32 bit sparcs, but we can't
figure that we are on a sparc64 while compiling user-space programs. */
#define __ATM_API_ALIGN __attribute__((aligned(8)))
#else
#define __ATM_API_ALIGN
#endif
/*
* Opaque type for kernel pointers. Note that _ is never accessed. We need
* the struct in order hide the array, so that we can make simple assignments
* instead of being forced to use memcpy. It also improves error reporting for
* code that still assumes that we're passing unsigned longs.
*
* Convention: NULL pointers are passed as a field of all zeroes.
*/
typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t;
#endif
/* atmioc.h - ranges for ATM-related ioctl numbers */
/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
/*
* See http://icawww1.epfl.ch/linux-atm/magic.html for the complete list of
* "magic" ioctl numbers.
*/
#ifndef _LINUX_ATMIOC_H
#define _LINUX_ATMIOC_H
#include <asm/ioctl.h>
/* everybody including atmioc.h will also need _IO{,R,W,WR} */
#define ATMIOC_PHYCOM 0x00 /* PHY device common ioctls, globally unique */
#define ATMIOC_PHYCOM_END 0x0f
#define ATMIOC_PHYTYP 0x10 /* PHY dev type ioctls, unique per PHY type */
#define ATMIOC_PHYTYP_END 0x2f
#define ATMIOC_PHYPRV 0x30 /* PHY dev private ioctls, unique per driver */
#define ATMIOC_PHYPRV_END 0x4f
#define ATMIOC_SARCOM 0x50 /* SAR device common ioctls, globally unique */
#define ATMIOC_SARCOM_END 0x50
#define ATMIOC_SARPRV 0x60 /* SAR dev private ioctls, unique per driver */
#define ATMIOC_SARPRV_END 0x7f
#define ATMIOC_ITF 0x80 /* Interface ioctls, globally unique */
#define ATMIOC_ITF_END 0x8f
#define ATMIOC_BACKEND 0x90 /* ATM generic backend ioctls, u. per backend */
#define ATMIOC_BACKEND_END 0xaf
/* 0xb0-0xbf: Reserved for future use */
#define ATMIOC_AREQUIPA 0xc0 /* Application requested IP over ATM, glob. u. */
#define ATMIOC_LANE 0xd0 /* LAN Emulation, globally unique */
#define ATMIOC_MPOA 0xd8 /* MPOA, globally unique */
#define ATMIOC_CLIP 0xe0 /* Classical IP over ATM control, globally u. */
#define ATMIOC_CLIP_END 0xef
#define ATMIOC_SPECIAL 0xf0 /* Special-purpose controls, globally unique */
#define ATMIOC_SPECIAL_END 0xff
#endif
/* atmsap.h - ATM Service Access Point addressing definitions */
/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
#ifndef _LINUX_ATMSAP_H
#define _LINUX_ATMSAP_H
#include <linux/atmapi.h>
/*
* BEGIN_xx and END_xx markers are used for automatic generation of
* documentation. Do not change them.
*/
/*
* Layer 2 protocol identifiers
*/
/* BEGIN_L2 */
#define ATM_L2_NONE 0 /* L2 not specified */
#define ATM_L2_ISO1745 0x01 /* Basic mode ISO 1745 */
#define ATM_L2_Q291 0x02 /* ITU-T Q.291 (Rec. I.441) */
#define ATM_L2_X25_LL 0x06 /* ITU-T X.25, link layer */
#define ATM_L2_X25_ML 0x07 /* ITU-T X.25, multilink */
#define ATM_L2_LAPB 0x08 /* Extended LAPB, half-duplex (Rec. T.71) */
#define ATM_L2_HDLC_ARM 0x09 /* HDLC ARM (ISO/IEC 4335) */
#define ATM_L2_HDLC_NRM 0x0a /* HDLC NRM (ISO/IEC 4335) */
#define ATM_L2_HDLC_ABM 0x0b /* HDLC ABM (ISO/IEC 4335) */
#define ATM_L2_ISO8802 0x0c /* LAN LLC (ISO/IEC 8802/2) */
#define ATM_L2_X75 0x0d /* ITU-T X.75, SLP */
#define ATM_L2_Q922 0x0e /* ITU-T Q.922 */
#define ATM_L2_USER 0x10 /* user-specified */
#define ATM_L2_ISO7776 0x11 /* ISO 7776 DTE-DTE */
/* END_L2 */
/*
* Layer 3 protocol identifiers
*/
/* BEGIN_L3 */
#define ATM_L3_NONE 0 /* L3 not specified */
#define ATM_L3_X25 0x06 /* ITU-T X.25, packet layer */
#define ATM_L3_ISO8208 0x07 /* ISO/IEC 8208 */
#define ATM_L3_X223 0x08 /* ITU-T X.223 | ISO/IEC 8878 */
#define ATM_L3_ISO8473 0x09 /* ITU-T X.233 | ISO/IEC 8473 */
#define ATM_L3_T70 0x0a /* ITU-T T.70 minimum network layer */
#define ATM_L3_TR9577 0x0b /* ISO/IEC TR 9577 */
#define ATM_L3_H310 0x0c /* ITU-T Recommendation H.310 */
#define ATM_L3_H321 0x0d /* ITU-T Recommendation H.321 */
#define ATM_L3_USER 0x10 /* user-specified */
/* END_L3 */
/*
* High layer identifiers
*/
/* BEGIN_HL */
#define ATM_HL_NONE 0 /* HL not specified */
#define ATM_HL_ISO 0x01 /* ISO */
#define ATM_HL_USER 0x02 /* user-specific */
#define ATM_HL_HLP 0x03 /* high layer profile - UNI 3.0 only */
#define ATM_HL_VENDOR 0x04 /* vendor-specific application identifier */
/* END_HL */
/*
* ITU-T coded mode of operation
*/
/* BEGIN_IMD */
#define ATM_IMD_NONE 0 /* mode not specified */
#define ATM_IMD_NORMAL 1 /* normal mode of operation */
#define ATM_IMD_EXTENDED 2 /* extended mode of operation */
/* END_IMD */
/*
* H.310 code points
*/
#define ATM_TT_NONE 0 /* terminal type not specified */
#define ATM_TT_RX 1 /* receive only */
#define ATM_TT_TX 2 /* send only */
#define ATM_TT_RXTX 3 /* receive and send */
#define ATM_MC_NONE 0 /* no multiplexing */
#define ATM_MC_TS 1 /* transport stream (TS) */
#define ATM_MC_TS_FEC 2 /* transport stream with forward error corr. */
#define ATM_MC_PS 3 /* program stream (PS) */
#define ATM_MC_PS_FEC 4 /* program stream with forward error corr. */
#define ATM_MC_H221 5 /* ITU-T Rec. H.221 */
/*
* SAP structures
*/
#define ATM_MAX_HLI 8 /* maximum high-layer information length */
struct atm_blli {
unsigned char l2_proto; /* layer 2 protocol */
union {
struct {
unsigned char mode; /* mode of operation (ATM_IMD_xxx), 0 if */
/* absent */
unsigned char window; /* window size (k), 1-127 (0 to omit) */
} itu; /* ITU-T encoding */
unsigned char user; /* user-specified l2 information */
} l2;
unsigned char l3_proto; /* layer 3 protocol */
union {
struct {
unsigned char mode; /* mode of operation (ATM_IMD_xxx), 0 if */
/* absent */
unsigned char def_size; /* default packet size (log2), 4-12 (0 to */
/* omit) */
unsigned char window;/* packet window size, 1-127 (0 to omit) */
} itu; /* ITU-T encoding */
unsigned char user; /* user specified l3 information */
struct { /* if l3_proto = ATM_L3_H310 */
unsigned char term_type; /* terminal type */
unsigned char fw_mpx_cap; /* forward multiplexing capability */
/* only if term_type != ATM_TT_NONE */
unsigned char bw_mpx_cap; /* backward multiplexing capability */
/* only if term_type != ATM_TT_NONE */
} h310;
struct { /* if l3_proto = ATM_L3_TR9577 */
unsigned char ipi; /* initial protocol id */
unsigned char snap[5];/* IEEE 802.1 SNAP identifier */
/* (only if ipi == NLPID_IEEE802_1_SNAP) */
} tr9577;
} l3;
} __ATM_API_ALIGN;
struct atm_bhli {
unsigned char hl_type; /* high layer information type */
unsigned char hl_length; /* length (only if hl_type == ATM_HL_USER || */
/* hl_type == ATM_HL_ISO) */
unsigned char hl_info[ATM_MAX_HLI];/* high layer information */
};
#define ATM_MAX_BLLI 3 /* maximum number of BLLI elements */
struct atm_sap {
struct atm_bhli bhli; /* local SAP, high-layer information */
struct atm_blli blli[ATM_MAX_BLLI] __ATM_API_ALIGN;
/* local SAP, low-layer info */
};
static __inline__ int blli_in_use(struct atm_blli blli)
{
return blli.l2_proto || blli.l3_proto;
}
#endif
...@@ -36,7 +36,8 @@ static void usage(void) ...@@ -36,7 +36,8 @@ static void usage(void)
{ {
fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n"); fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
fprintf(stderr, " [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"); fprintf(stderr, " [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n");
fprintf(stderr, " [ ACTIONTERM ]\n"); fprintf(stderr, " [ linklayer TYPE ] [ ACTIONTERM ]\n");
fprintf(stderr, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n"); fprintf(stderr, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n");
fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n"); fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n");
fprintf(stderr, "Where: *EXCEEDACT := pipe | ok | reclassify | drop | continue \n"); fprintf(stderr, "Where: *EXCEEDACT := pipe | ok | reclassify | drop | continue \n");
...@@ -134,6 +135,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_ ...@@ -134,6 +135,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
int presult = 0; int presult = 0;
unsigned buffer=0, mtu=0, mpu=0; unsigned buffer=0, mtu=0, mpu=0;
unsigned short overhead=0; unsigned short overhead=0;
unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
int Rcell_log=-1, Pcell_log = -1; int Rcell_log=-1, Pcell_log = -1;
struct rtattr *tail; struct rtattr *tail;
...@@ -240,6 +242,11 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_ ...@@ -240,6 +242,11 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
if (get_u16(&overhead, *argv, 10)) { if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1; explain1("overhead"); return -1;
} }
} else if (matches(*argv, "linklayer") == 0) {
NEXT_ARG();
if (get_linklayer(&linklayer, *argv)) {
explain1("linklayer"); return -1;
}
} else if (strcmp(*argv, "help") == 0) { } else if (strcmp(*argv, "help") == 0) {
usage(); usage();
} else { } else {
...@@ -270,7 +277,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_ ...@@ -270,7 +277,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
if (p.rate.rate) { if (p.rate.rate) {
p.rate.mpu = mpu; p.rate.mpu = mpu;
p.rate.overhead = overhead; p.rate.overhead = overhead;
if (tc_calc_rtable(&p.rate, rtab, Rcell_log, mtu) < 0) { if (tc_calc_rtable(&p.rate, rtab, Rcell_log, mtu, linklayer) < 0) {
fprintf(stderr, "TBF: failed to calculate rate table.\n"); fprintf(stderr, "TBF: failed to calculate rate table.\n");
return -1; return -1;
} }
...@@ -280,7 +287,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_ ...@@ -280,7 +287,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
if (p.peakrate.rate) { if (p.peakrate.rate) {
p.peakrate.mpu = mpu; p.peakrate.mpu = mpu;
p.peakrate.overhead = overhead; p.peakrate.overhead = overhead;
if (tc_calc_rtable(&p.peakrate, ptab, Pcell_log, mtu) < 0) { if (tc_calc_rtable(&p.peakrate, ptab, Pcell_log, mtu, linklayer) < 0) {
fprintf(stderr, "POLICE: failed to calculate peak rate table.\n"); fprintf(stderr, "POLICE: failed to calculate peak rate table.\n");
return -1; return -1;
} }
......
...@@ -32,7 +32,7 @@ static void explain_class(void) ...@@ -32,7 +32,7 @@ static void explain_class(void)
fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n"); fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n"); fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n");
fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n"); fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n");
fprintf(stderr, " [ overhead BYTES ]\n"); fprintf(stderr, " [ overhead BYTES ] [ linklayer TYPE ]\n");
} }
static void explain(void) static void explain(void)
...@@ -55,6 +55,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -55,6 +55,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
__u32 rtab[256]; __u32 rtab[256];
unsigned mpu=0, avpkt=0, allot=0; unsigned mpu=0, avpkt=0, allot=0;
unsigned short overhead=0; unsigned short overhead=0;
unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
int cell_log=-1; int cell_log=-1;
int ewma_log=-1; int ewma_log=-1;
struct rtattr *tail; struct rtattr *tail;
...@@ -120,6 +121,11 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -120,6 +121,11 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
if (get_u16(&overhead, *argv, 10)) { if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1; explain1("overhead"); return -1;
} }
} else if (matches(*argv, "linklayer") == 0) {
NEXT_ARG();
if (get_linklayer(&linklayer, *argv)) {
explain1("linklayer"); return -1;
}
} else if (matches(*argv, "help") == 0) { } else if (matches(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;
...@@ -146,7 +152,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -146,7 +152,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
r.mpu = mpu; r.mpu = mpu;
r.overhead = overhead; r.overhead = overhead;
if (tc_calc_rtable(&r, rtab, cell_log, allot) < 0) { if (tc_calc_rtable(&r, rtab, cell_log, allot, linklayer) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n"); fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1; return -1;
} }
...@@ -188,6 +194,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -188,6 +194,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
unsigned bndw = 0; unsigned bndw = 0;
unsigned minburst=0, maxburst=0; unsigned minburst=0, maxburst=0;
unsigned short overhead=0; unsigned short overhead=0;
unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
struct rtattr *tail; struct rtattr *tail;
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
...@@ -331,6 +338,11 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -331,6 +338,11 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
if (get_u16(&overhead, *argv, 10)) { if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1; explain1("overhead"); return -1;
} }
} else if (matches(*argv, "linklayer") == 0) {
NEXT_ARG();
if (get_linklayer(&linklayer, *argv)) {
explain1("linklayer"); return -1;
}
} else if (matches(*argv, "help") == 0) { } else if (matches(*argv, "help") == 0) {
explain_class(); explain_class();
return -1; return -1;
...@@ -351,7 +363,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -351,7 +363,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
wrr.allot = (lss.avpkt*3)/2; wrr.allot = (lss.avpkt*3)/2;
r.mpu = mpu; r.mpu = mpu;
r.overhead = overhead; r.overhead = overhead;
if (tc_calc_rtable(&r, rtab, cell_log, pktsize) < 0) { if (tc_calc_rtable(&r, rtab, cell_log, pktsize, linklayer) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n"); fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1; return -1;
} }
......
...@@ -41,7 +41,7 @@ static void explain(void) ...@@ -41,7 +41,7 @@ static void explain(void)
" burst max bytes burst which can be accumulated during idle period {computed}\n" " burst max bytes burst which can be accumulated during idle period {computed}\n"
" mpu minimum packet size used in rate computations\n" " mpu minimum packet size used in rate computations\n"
" overhead per-packet size overhead used in rate computations\n" " overhead per-packet size overhead used in rate computations\n"
" linklay adapting to a linklayer e.g. atm\n"
" ceil definite upper class rate (no borrows) {rate}\n" " ceil definite upper class rate (no borrows) {rate}\n"
" cburst burst but for ceil {computed}\n" " cburst burst but for ceil {computed}\n"
" mtu max packet size we create rate map for {1600}\n" " mtu max packet size we create rate map for {1600}\n"
...@@ -110,6 +110,7 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -110,6 +110,7 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
unsigned mtu; unsigned mtu;
unsigned short mpu = 0; unsigned short mpu = 0;
unsigned short overhead = 0; unsigned short overhead = 0;
unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
struct rtattr *tail; struct rtattr *tail;
memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */ memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
...@@ -136,6 +137,11 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -136,6 +137,11 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
if (get_u16(&overhead, *argv, 10)) { if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1; explain1("overhead"); return -1;
} }
} else if (matches(*argv, "linklayer") == 0) {
NEXT_ARG();
if (get_linklayer(&linklayer, *argv)) {
explain1("linklayer"); return -1;
}
} else if (matches(*argv, "quantum") == 0) { } else if (matches(*argv, "quantum") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_u32(&opt.quantum, *argv, 10)) { if (get_u32(&opt.quantum, *argv, 10)) {
...@@ -213,13 +219,13 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str ...@@ -213,13 +219,13 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
opt.ceil.mpu = mpu; opt.ceil.mpu = mpu;
opt.rate.mpu = mpu; opt.rate.mpu = mpu;
if (tc_calc_rtable(&opt.rate, rtab, cell_log, mtu) < 0) { if (tc_calc_rtable(&opt.rate, rtab, cell_log, mtu, linklayer) < 0) {
fprintf(stderr, "htb: failed to calculate rate table.\n"); fprintf(stderr, "htb: failed to calculate rate table.\n");
return -1; return -1;
} }
opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer); opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
if (tc_calc_rtable(&opt.ceil, ctab, ccell_log, mtu) < 0) { if (tc_calc_rtable(&opt.ceil, ctab, ccell_log, mtu, linklayer) < 0) {
fprintf(stderr, "htb: failed to calculate ceil rate table.\n"); fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
return -1; return -1;
} }
......
...@@ -27,7 +27,7 @@ static void explain(void) ...@@ -27,7 +27,7 @@ static void explain(void)
{ {
fprintf(stderr, "Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n"); fprintf(stderr, "Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n");
fprintf(stderr, " [ peakrate KBPS ] [ latency TIME ] "); fprintf(stderr, " [ peakrate KBPS ] [ latency TIME ] ");
fprintf(stderr, "[ overhead BYTES ]\n"); fprintf(stderr, "[ overhead BYTES ] [ linklayer TYPE ]\n");
} }
static void explain1(char *arg) static void explain1(char *arg)
...@@ -47,6 +47,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -47,6 +47,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
unsigned buffer=0, mtu=0, mpu=0, latency=0; unsigned buffer=0, mtu=0, mpu=0, latency=0;
int Rcell_log=-1, Pcell_log = -1; int Rcell_log=-1, Pcell_log = -1;
unsigned short overhead=0; unsigned short overhead=0;
unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
struct rtattr *tail; struct rtattr *tail;
memset(&opt, 0, sizeof(opt)); memset(&opt, 0, sizeof(opt));
...@@ -141,6 +142,11 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -141,6 +142,11 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
if (get_u16(&overhead, *argv, 10)) { if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1; explain1("overhead"); return -1;
} }
} else if (matches(*argv, "linklayer") == 0) {
NEXT_ARG();
if (get_linklayer(&linklayer, *argv)) {
explain1("linklayer"); return -1;
}
} else if (strcmp(*argv, "help") == 0) { } else if (strcmp(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;
...@@ -183,7 +189,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -183,7 +189,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
opt.rate.mpu = mpu; opt.rate.mpu = mpu;
opt.rate.overhead = overhead; opt.rate.overhead = overhead;
if (tc_calc_rtable(&opt.rate, rtab, Rcell_log, mtu) < 0) { if (tc_calc_rtable(&opt.rate, rtab, Rcell_log, mtu, linklayer) < 0) {
fprintf(stderr, "TBF: failed to calculate rate table.\n"); fprintf(stderr, "TBF: failed to calculate rate table.\n");
return -1; return -1;
} }
...@@ -192,7 +198,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl ...@@ -192,7 +198,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
if (opt.peakrate.rate) { if (opt.peakrate.rate) {
opt.peakrate.mpu = mpu; opt.peakrate.mpu = mpu;
opt.peakrate.overhead = overhead; opt.peakrate.overhead = overhead;
if (tc_calc_rtable(&opt.peakrate, ptab, Pcell_log, mtu) < 0) { if (tc_calc_rtable(&opt.peakrate, ptab, Pcell_log, mtu, linklayer) < 0) {
fprintf(stderr, "TBF: failed to calculate peak rate table.\n"); fprintf(stderr, "TBF: failed to calculate peak rate table.\n");
return -1; return -1;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <string.h> #include <string.h>
#include "tc_core.h" #include "tc_core.h"
#include <linux/atm.h>
static double tick_in_usec = 1; static double tick_in_usec = 1;
static double clock_factor = 1; static double clock_factor = 1;
...@@ -65,11 +66,34 @@ unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks) ...@@ -65,11 +66,34 @@ unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks)
return ((double)rate*tc_core_tick2time(ticks))/TIME_UNITS_PER_SEC; return ((double)rate*tc_core_tick2time(ticks))/TIME_UNITS_PER_SEC;
} }
/*
* The align to ATM cells is used for determining the (ATM) SAR
* alignment overhead at the ATM layer. (SAR = Segmentation And
* Reassembly). This is for example needed when scheduling packet on
* an ADSL connection. Note that the extra ATM-AAL overhead is _not_
* included in this calculation. This overhead is added in the kernel
* before doing the rate table lookup, as this gives better precision
* (as the table will always be aligned for 48 bytes).
* --Hawk, d.7/11-2004. <hawk@diku.dk>
*/
unsigned tc_align_to_atm(unsigned size)
{
int linksize, cells;
cells = size / ATM_CELL_PAYLOAD;
if ((size % ATM_CELL_PAYLOAD) > 0)
cells++;
linksize = cells * ATM_CELL_SIZE; /* Use full cell size to add ATM tax */
return linksize;
}
/* /*
rtab[pkt_len>>cell_log] = pkt_xmit_time rtab[pkt_len>>cell_log] = pkt_xmit_time
*/ */
int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, int cell_log, unsigned mtu) int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
int cell_log, unsigned mtu,
enum link_layer linklayer)
{ {
int i; int i;
unsigned bps = r->rate; unsigned bps = r->rate;
...@@ -80,15 +104,29 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, int cell_log, unsigned mt ...@@ -80,15 +104,29 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, int cell_log, unsigned mt
if (cell_log < 0) { if (cell_log < 0) {
cell_log = 0; cell_log = 0;
while ((mtu>>cell_log) > 255) while ((mtu >> cell_log) > 255)
cell_log++; cell_log++;
} }
for (i=0; i<256; i++) { for (i=0; i<256; i++) {
unsigned sz = ((i+1)<<cell_log); unsigned sz = (i+1)<<cell_log;
if (sz < mpu) if (sz < mpu)
sz = mpu; sz = mpu;
switch (linklayer) {
case LINKLAYER_ATM:
sz = tc_align_to_atm(sz);
break;
case LINKLAYER_ETHERNET:
// No size adjustments on Ethernet
break;
default:
break;
}
rtab[i] = tc_calc_xmittime(bps, sz); rtab[i] = tc_calc_xmittime(bps, sz);
} }
r->cell_align=-1; // Due to the sz calc r->cell_align=-1; // Due to the sz calc
r->cell_log=cell_log; r->cell_log=cell_log;
return cell_log; return cell_log;
......
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
#define TIME_UNITS_PER_SEC 1000000 #define TIME_UNITS_PER_SEC 1000000
enum link_layer {
LINKLAYER_ETHERNET=1,
LINKLAYER_ATM =2,
};
int tc_core_time2big(unsigned time); int tc_core_time2big(unsigned time);
unsigned tc_core_time2tick(unsigned time); unsigned tc_core_time2tick(unsigned time);
unsigned tc_core_tick2time(unsigned tick); unsigned tc_core_tick2time(unsigned tick);
...@@ -13,7 +19,8 @@ unsigned tc_core_time2ktime(unsigned time); ...@@ -13,7 +19,8 @@ unsigned tc_core_time2ktime(unsigned time);
unsigned tc_core_ktime2time(unsigned ktime); unsigned tc_core_ktime2time(unsigned ktime);
unsigned tc_calc_xmittime(unsigned rate, unsigned size); unsigned tc_calc_xmittime(unsigned rate, unsigned size);
unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks); unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks);
int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, int cell_log, unsigned mtu); int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
int cell_log, unsigned mtu, enum link_layer link_layer);
int tc_setup_estimator(unsigned A, unsigned time_const, struct tc_estimator *est); int tc_setup_estimator(unsigned A, unsigned time_const, struct tc_estimator *est);
......
...@@ -435,6 +435,23 @@ int action_a2n(char *arg, int *result) ...@@ -435,6 +435,23 @@ int action_a2n(char *arg, int *result)
return 0; return 0;
} }
int get_linklayer(unsigned int *val, const char *arg)
{
int res;
if (matches(arg, "ethernet") == 0)
res = LINKLAYER_ETHERNET;
else if (matches(arg, "atm") == 0)
res = LINKLAYER_ATM;
else if (matches(arg, "adsl") == 0)
res = LINKLAYER_ATM;
else
return -1; /* Indicate error */
*val = res;
return 0;
}
void print_tm(FILE * f, const struct tcf_t *tm) void print_tm(FILE * f, const struct tcf_t *tm)
{ {
int hz = get_user_hz(); int hz = get_user_hz();
......
...@@ -49,6 +49,8 @@ extern int get_percent(unsigned *percent, const char *str); ...@@ -49,6 +49,8 @@ extern int get_percent(unsigned *percent, const char *str);
extern int get_size(unsigned *size, const char *str); extern int get_size(unsigned *size, const char *str);
extern int get_size_and_cell(unsigned *size, int *cell_log, char *str); extern int get_size_and_cell(unsigned *size, int *cell_log, char *str);
extern int get_time(unsigned *time, const char *str); extern int get_time(unsigned *time, const char *str);
extern int get_linklayer(unsigned *val, const char *arg);
extern void print_rate(char *buf, int len, __u32 rate); extern void print_rate(char *buf, int len, __u32 rate);
extern void print_size(char *buf, int len, __u32 size); extern void print_size(char *buf, int len, __u32 size);
extern void print_percent(char *buf, int len, __u32 percent); extern void print_percent(char *buf, int len, __u32 percent);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment