181 lines
4.0 KiB
C
181 lines
4.0 KiB
C
/* text2qos.c - Converts textual representation of QOS parameters to binary
|
|
encoding */
|
|
|
|
/* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
|
|
|
|
#if HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <limits.h>
|
|
|
|
#include "atm.h"
|
|
|
|
|
|
#define fetch __atmlib_fetch
|
|
|
|
|
|
#define RATE_ERROR -2
|
|
|
|
|
|
int __t2q_get_rate(const char **text,int up)
|
|
{
|
|
const char mult[] = "kKmMgGg";
|
|
const char *multiplier;
|
|
char *end;
|
|
unsigned int rate,fract;
|
|
int power;
|
|
|
|
if (!strncmp(*text,"max",3)) {
|
|
*text += 3;
|
|
return ATM_MAX_PCR;
|
|
}
|
|
rate = strtoul(*text,&end,10);
|
|
power = fract = 0;
|
|
if (*end == '.')
|
|
for (end++; *end && isdigit(*end); end++) {
|
|
fract = fract*10+*end-48;
|
|
if (--power == -9) break;
|
|
}
|
|
multiplier = NULL;
|
|
if (*end && (multiplier = strchr(mult,*end))) {
|
|
while (multiplier >= mult) {
|
|
if (rate > UINT_MAX/1000) return RATE_ERROR;
|
|
rate *= 1000;
|
|
power += 3;
|
|
multiplier -= 2;
|
|
}
|
|
end++;
|
|
}
|
|
while (power && fract)
|
|
if (power < 0) {
|
|
fract /= 10;
|
|
power++;
|
|
}
|
|
else {
|
|
fract *= 10;
|
|
power--;
|
|
}
|
|
rate += fract;
|
|
if (strlen(end) < 3) {
|
|
if (multiplier) return RATE_ERROR;
|
|
}
|
|
else if (!strncmp(end,"cps",3)) end += 3;
|
|
else if (!strncmp(end,"bps",3)) {
|
|
rate = (rate+(up ? 8*ATM_CELL_PAYLOAD-1 : 0))/8/
|
|
ATM_CELL_PAYLOAD;
|
|
end += 3;
|
|
}
|
|
else if (multiplier) return RATE_ERROR;
|
|
if (rate > INT_MAX) return RATE_ERROR;
|
|
*text = end;
|
|
return rate;
|
|
}
|
|
|
|
|
|
static int params(const char **text,struct atm_trafprm *a,
|
|
struct atm_trafprm *b)
|
|
{
|
|
int value;
|
|
char *end;
|
|
|
|
if (*(*text)++ != ':') return -1;
|
|
while (1) {
|
|
if (!**text) return -1;
|
|
switch (fetch(text,"max_pcr=","pcr=","min_pcr=","max_sdu=","sdu=",
|
|
NULL)) {
|
|
case 0:
|
|
if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
|
|
if (a) a->max_pcr = value;
|
|
if (b) b->max_pcr = value;
|
|
break;
|
|
case 1:
|
|
if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
|
|
if (a) a->pcr = value;
|
|
if (b) b->pcr = value;
|
|
break;
|
|
case 2:
|
|
if ((value = __t2q_get_rate(text,1)) == RATE_ERROR) return -1;
|
|
if (value == ATM_MAX_PCR) return -1;
|
|
if (a) a->min_pcr = value;
|
|
if (b) b->min_pcr = value;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
value = strtol(*text,&end,10);
|
|
if (value < 0) return -1;
|
|
*text = end;
|
|
if (a) a->max_sdu = value;
|
|
if (b) b->max_sdu = value;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
if (!**text) break;
|
|
if (*(*text)++ != ',') return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int text2qos(const char *text,struct atm_qos *qos,int flags)
|
|
{
|
|
int traffic_class,aal;
|
|
|
|
traffic_class = ATM_NONE;
|
|
aal = ATM_NO_AAL;
|
|
do {
|
|
static const unsigned char aal_number[] = { ATM_AAL0, ATM_AAL5 };
|
|
int item;
|
|
|
|
item = fetch(&text,"!none","ubr","cbr","vbr","abr","aal0","aal5",NULL);
|
|
switch (item) {
|
|
case 1:
|
|
case 2:
|
|
/* we don't support VBR yet */
|
|
case 4:
|
|
traffic_class = item;
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
aal = aal_number[item-5];
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
while (*text == ',' ? text++ : 0);
|
|
if (!traffic_class) return -1;
|
|
if (qos && !(flags & T2Q_DEFAULTS)) memset(qos,0,sizeof(*qos));
|
|
if (qos) qos->txtp.traffic_class = qos->rxtp.traffic_class = traffic_class;
|
|
if (qos && aal) qos->aal = aal;
|
|
if (!*text) return 0;
|
|
if (params(&text,qos ? &qos->txtp : NULL,qos ? &qos->rxtp : NULL))
|
|
return -1;
|
|
if (!*text) return 0;
|
|
switch (fetch(&text,"tx","rx",NULL)) {
|
|
case 0:
|
|
if (!fetch(&text,":none",NULL)) {
|
|
if (qos) qos->txtp.traffic_class = ATM_NONE;
|
|
if (*text == ',') text++;
|
|
break;
|
|
}
|
|
if (params(&text,qos ? &qos->txtp : NULL,NULL)) return -1;
|
|
break;
|
|
case 1:
|
|
text -= 2;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
if (!*text) return 0;
|
|
if (fetch(&text,"rx",NULL)) return -1;
|
|
if (!fetch(&text,":none",NULL) && qos) qos->rxtp.traffic_class = ATM_NONE;
|
|
else if (params(&text,qos ? &qos->rxtp : NULL,NULL)) return -1;
|
|
return *text ? -1 : 0;
|
|
}
|