]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ATM cell alignment.
authorJesper Dangaard Brouer <hawk@diku.dk>
Wed, 9 Apr 2008 21:01:01 +0000 (23:01 +0200)
committerStephen Hemminger <stephen.hemminger@vyatta.com>
Thu, 17 Apr 2008 17:04:31 +0000 (10:04 -0700)
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: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
12 files changed:
include/linux/atm.h [new file with mode: 0644]
include/linux/atmapi.h [new file with mode: 0644]
include/linux/atmioc.h [new file with mode: 0644]
include/linux/atmsap.h [new file with mode: 0644]
tc/m_police.c
tc/q_cbq.c
tc/q_htb.c
tc/q_tbf.c
tc/tc_core.c
tc/tc_core.h
tc/tc_util.c
tc/tc_util.h

diff --git a/include/linux/atm.h b/include/linux/atm.h
new file mode 100644 (file)
index 0000000..593e6c1
--- /dev/null
@@ -0,0 +1,238 @@
+/* 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
diff --git a/include/linux/atmapi.h b/include/linux/atmapi.h
new file mode 100644 (file)
index 0000000..8fe54d9
--- /dev/null
@@ -0,0 +1,29 @@
+/* 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
diff --git a/include/linux/atmioc.h b/include/linux/atmioc.h
new file mode 100644 (file)
index 0000000..37f67aa
--- /dev/null
@@ -0,0 +1,41 @@
+/* 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
diff --git a/include/linux/atmsap.h b/include/linux/atmsap.h
new file mode 100644 (file)
index 0000000..799b104
--- /dev/null
@@ -0,0 +1,162 @@
+/* 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
index e55a8c9c1e57522c2969bf2a1900aab24f691a9f..ace43b52bbf7a7fb4409b8784da5322d8b4307b6 100644 (file)
@@ -36,7 +36,8 @@ static void usage(void)
 {
        fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/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, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \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_
        int presult = 0;
        unsigned buffer=0, mtu=0, mpu=0;
        unsigned short overhead=0;
+       unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
        int Rcell_log=-1, Pcell_log = -1;
        struct rtattr *tail;
 
@@ -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)) {
                                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) {
                        usage();
                } else {
@@ -270,7 +277,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
        if (p.rate.rate) {
                p.rate.mpu = mpu;
                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");
                        return -1;
                }
@@ -280,7 +287,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
        if (p.peakrate.rate) {
                p.peakrate.mpu = mpu;
                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");
                        return -1;
                }
index e53d1673eef45c312174ed0ec0de7bce5e347f28..c99dc3b6fbcb2d4ff4d871337a2c2ff4ba741cf8 100644 (file)
@@ -32,7 +32,7 @@ static void explain_class(void)
        fprintf(stderr, "               [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
        fprintf(stderr, "               [ estimator INTERVAL TIME_CONSTANT ]\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)
@@ -55,6 +55,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
        __u32 rtab[256];
        unsigned mpu=0, avpkt=0, allot=0;
        unsigned short overhead=0;
+       unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
        int cell_log=-1;
        int ewma_log=-1;
        struct rtattr *tail;
@@ -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)) {
                                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) {
                        explain();
                        return -1;
@@ -146,7 +152,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
 
        r.mpu = mpu;
        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");
                return -1;
        }
@@ -188,6 +194,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
        unsigned bndw = 0;
        unsigned minburst=0, maxburst=0;
        unsigned short overhead=0;
+       unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
        struct rtattr *tail;
 
        memset(&r, 0, sizeof(r));
@@ -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)) {
                                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) {
                        explain_class();
                        return -1;
@@ -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;
                r.mpu = mpu;
                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");
                        return -1;
                }
index e24ad6de3f798498333806a003f124609b692502..c69e350d0735a090d3e4000683c23dd0771371eb 100644 (file)
@@ -41,7 +41,7 @@ static void explain(void)
                " burst    max bytes burst which can be accumulated during idle period {computed}\n"
                " mpu      minimum packet size 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"
                " cburst   burst but for ceil {computed}\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
        unsigned mtu;
        unsigned short mpu = 0;
        unsigned short overhead = 0;
+       unsigned int linklayer  = LINKLAYER_ETHERNET; /* Assume ethernet */
        struct rtattr *tail;
 
        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
                        if (get_u16(&overhead, *argv, 10)) {
                                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) {
                        NEXT_ARG();
                        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
        opt.ceil.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");
                return -1;
        }
        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");
                return -1;
        }
index 3bdce5a4b7aef5292065481eacb8634e7d805a25..dbf95863bef7769b8fc5d2a992c40c85bed7adcd 100644 (file)
@@ -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, "               [ peakrate KBPS ] [ latency TIME ] ");
-       fprintf(stderr, "[ overhead BYTES ]\n");
+       fprintf(stderr, "[ overhead BYTES ] [ linklayer TYPE ]\n");
 }
 
 static void explain1(char *arg)
@@ -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;
        int Rcell_log=-1, Pcell_log = -1;
        unsigned short overhead=0;
+       unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
        struct rtattr *tail;
 
        memset(&opt, 0, sizeof(opt));
@@ -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)) {
                                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) {
                        explain();
                        return -1;
@@ -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.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");
                return -1;
        }
@@ -192,7 +198,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
        if (opt.peakrate.rate) {
                opt.peakrate.mpu      = mpu;
                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");
                        return -1;
                }
index 9ae4d8e5e7e9f0da847ff2074b464111bae9f7ad..855c11546570f9b32ae5c70339ee01463dfe0484 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 
 #include "tc_core.h"
+#include <linux/atm.h>
 
 static double tick_in_usec = 1;
 static double clock_factor = 1;
@@ -65,11 +66,34 @@ unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks)
        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
  */
 
-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;
        unsigned bps = r->rate;
@@ -80,15 +104,29 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, int cell_log, unsigned mt
 
        if (cell_log < 0) {
                cell_log = 0;
-               while ((mtu>>cell_log) > 255)
+               while ((mtu >> cell_log) > 255)
                        cell_log++;
        }
+
        for (i=0; i<256; i++) {
-               unsigned sz = ((i+1)<<cell_log);
+               unsigned sz = (i+1)<<cell_log;
                if (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);
        }
+
        r->cell_align=-1; // Due to the sz calc
        r->cell_log=cell_log;
        return cell_log;
index 080a0cdac4cdcd484cbdd490b6ab7289b0ad2406..9f835e8d053a0b4fecf571215b56276ee0e6bec6 100644 (file)
@@ -6,6 +6,12 @@
 
 #define TIME_UNITS_PER_SEC     1000000
 
+enum link_layer {
+       LINKLAYER_ETHERNET=1,
+       LINKLAYER_ATM     =2,
+};
+
+
 int  tc_core_time2big(unsigned time);
 unsigned tc_core_time2tick(unsigned time);
 unsigned tc_core_tick2time(unsigned tick);
@@ -13,7 +19,8 @@ unsigned tc_core_time2ktime(unsigned time);
 unsigned tc_core_ktime2time(unsigned ktime);
 unsigned tc_calc_xmittime(unsigned rate, unsigned size);
 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);
 
index cdbae4217092f0c2e948ef08e2611b2800647ca9..cd9dd59423d586af591ccc761d7c6a786588a109 100644 (file)
@@ -435,6 +435,23 @@ int action_a2n(char *arg, int *result)
        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)
 {
        int hz = get_user_hz();
index 120d6cebaa93fcc478077af058bb637dc6b32799..301b5c7ff7ceb1c71ac776188bc4309e4719592b 100644 (file)
@@ -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_and_cell(unsigned *size, int *cell_log, 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_size(char *buf, int len, __u32 size);
 extern void print_percent(char *buf, int len, __u32 percent);