diff -ur --new-file old/atm/CHANGES new/atm/CHANGES --- old/atm/CHANGES Wed Aug 19 18:19:02 1998 +++ new/atm/CHANGES Wed Aug 19 19:03:02 1998 @@ -1,3 +1,12 @@ +Version 0.41 to 0.42 (19-AUG-1998) +==================== + +Bug fixes +--------- + + - atm.patch was out of sync again :-( + + Version 0.40 to 0.41 (19-AUG-1998) ==================== diff -ur --new-file old/atm/README new/atm/README --- old/atm/README Tue Aug 18 12:59:59 1998 +++ new/atm/README Wed Aug 19 19:03:09 1998 @@ -1,4 +1,4 @@ -ATM on Linux, release 0.41 (alpha) by Werner Almesberger, EPFL ICA +ATM on Linux, release 0.42 (alpha) by Werner Almesberger, EPFL ICA ============================================== Werner.Almesberger@epfl.ch This is experimental software. There are known major bugs and certainly diff -ur --new-file old/atm/USAGE new/atm/USAGE --- old/atm/USAGE Wed Aug 19 16:45:55 1998 +++ new/atm/USAGE Wed Aug 19 19:04:05 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.41 +Usage instructions - ATM on Linux, release 0.42 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,7 +17,7 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.41.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.42.tar.gz - the Linux kernel, version 2.1.105, e.g. from ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz - Perl, version 4 or 5 @@ -33,7 +33,7 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.41.tar.gz +tar xfz atm-0.42.tar.gz and the kernel source: diff -ur --new-file old/atm/VERSION new/atm/VERSION --- old/atm/VERSION Wed Aug 19 16:39:21 1998 +++ new/atm/VERSION Wed Aug 19 19:03:54 1998 @@ -1 +1 @@ -0.41 +0.42 diff -ur --new-file old/atm/atm.patch new/atm/atm.patch --- old/atm/atm.patch Wed Aug 19 16:45:43 1998 +++ new/atm/atm.patch Wed Aug 19 19:02:34 1998 @@ -7370,7 +7370,7 @@ +}; +#endif /* _ATMLEC_H_ */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmmpc.h Wed Aug 19 14:59:32 1998 ++++ work/include/linux/atmmpc.h Wed Aug 19 18:48:36 1998 @@ -0,0 +1,98 @@ +#ifndef _ATMMPC_H_ +#define _ATMMPC_H_ @@ -7396,7 +7396,6 @@ + uint8_t eg_MPC_ATM_addr[ATM_ESA_LEN]; + uint32_t tag; + uint32_t in_dst_ip; /* IP address this ingress MPC sends packets to */ -+ uint32_t service_category; + uint16_t holding_time; + uint32_t request_id; +} in_ctrl_info; @@ -7419,6 +7418,7 @@ + in_ctrl_info in_info; + eg_ctrl_info eg_info; + } content; ++ struct atm_qos qos; /* only used with content.in_info */ +} k_message; + +struct llc_snap_hdr { /* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */ @@ -12958,8 +12958,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpc.c Wed Aug 12 20:57:27 1998 -@@ -0,0 +1,1270 @@ ++++ work/net/atm/mpc.c Wed Aug 19 18:49:00 1998 +@@ -0,0 +1,1406 @@ +#include +#include +#include @@ -13062,6 +13062,7 @@ +#endif + +struct mpoa_client *mpcs = NULL; /* FIXME */ ++static struct atm_mpoa_qos *qos_head = NULL; +static struct timer_list mpc_timer; + + @@ -13107,6 +13108,100 @@ + return NULL; /* not found */ +} + ++/* ++ * Functions for managing QoS list ++ */ ++ ++/* ++ * Returns the new entry. Note the use of the 2nd argument ++ */ ++struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos) ++{ ++ struct atm_mpoa_qos *entry; ++ ++ entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL); ++ if (entry == NULL) { ++ printk("mpoa: atm_mpoa_add_qos: out of memory\n"); ++ return entry; ++ } ++ ++ entry->ipaddr = dst_ip; ++ entry->qos = *qos; ++ ++ entry->next = qos_head; ++ qos_head = entry; ++ ++ return entry; ++} ++ ++struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip) ++{ ++ struct atm_mpoa_qos *qos; ++ ++ qos = qos_head; ++ while( qos != NULL ){ ++ if(qos->ipaddr == dst_ip) { ++ break; ++ } ++ qos = qos->next; ++ } ++ ++ return qos; ++} ++ ++/* ++ * Returns 0 for failure ++ */ ++int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry) ++{ ++ ++ struct atm_mpoa_qos *curr; ++ ++ if (entry == NULL) return 0; ++ if (entry == qos_head) { ++ qos_head = qos_head->next; ++ kfree(qos_head); ++ return 1; ++ } ++ ++ curr = qos_head; ++ while (curr != NULL) { ++ if (curr->next == entry) { ++ curr->next = entry->next; ++ kfree(entry); ++ return 1; ++ } ++ curr = curr->next; ++ } ++ ++ return 0; ++} ++ ++void atm_mpoa_disp_qos(char *page, int *len) ++{ ++ ++ unsigned char *ip; ++ char ipaddr[16]; ++ struct atm_mpoa_qos *qos; ++ ++ qos = qos_head; ++ *len += sprintf(page + *len, "QoS entries for shortcuts:\n"); ++ *len += sprintf(page + *len, "IP address TX:max_pcr pcr min_pcr max_cdv max_sdu RX:max_pcr pcr min_pcr max_cdv max_sdu\n"); ++ ++ ipaddr[sizeof(ipaddr)-1] = '\0'; ++ while (qos != NULL) { ++ ip = (unsigned char *)&qos->ipaddr; ++ sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); ++ *len += sprintf(page + *len, "%-16s %-7d %-7d %-7d %-7d %-7d %-7d %-7d %-7d %-7d %-7d\n", ++ ipaddr, ++ qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, ++ qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); ++ qos = qos->next; ++ } ++ ++ return; ++} ++ +static struct device *find_lec_by_itfnum(int itf) +{ + extern struct atm_lane_ops atm_lane_ops; /* in common.c */ @@ -13125,7 +13220,7 @@ + if (mpc == NULL) + return NULL; + memset(mpc, 0, sizeof(struct mpoa_client)); -+#if 0 ++#if 0 /* compiler seems to barf on this */ + mpc->ingress_lock = RW_LOCK_UNLOCKED; + mpc->egress_lock = RW_LOCK_UNLOCKED; +#endif @@ -13559,6 +13654,7 @@ + return; + } + ++ eg->latest_ip_addr = ((struct iphdr *)new_skb->data)->saddr; + eg->packets_rcvd++; + + netif_rx(new_skb); @@ -13884,15 +13980,20 @@ + +static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *client) +{ ++ unsigned char *ip; ++ struct atm_mpoa_qos *qos; + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + in_cache_entry *entry = client->in_ops->search(dst_ip, client); ++ eg_cache_entry *eg_entry; + -+ dprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry); ++ ip = (unsigned char *)&dst_ip; ++ dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %d.%d.%d.%d\n", client->dev->name, ip[0], ip[1], ip[2], ip[3]); ++ ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry); + if(entry == NULL){ + printk("\nmpoa: (%s): ARGH, received res. reply for an entry that doesn't exist.\n", client->dev->name); + return; + } -+ printk(" entry_state = %d ", entry->entry_state); ++ ddprintk(" entry_state = %d ", entry->entry_state); + + if (entry->entry_state == INGRESS_RESOLVED) { + printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", client->dev->name); @@ -13903,21 +14004,47 @@ + do_gettimeofday(&(entry->tv)); + do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */ + entry->refresh_time = 0; -+ printk("entry->shortcut = %p\n", entry->shortcut); ++ ddprintk("entry->shortcut = %p\n", entry->shortcut); + + if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){ + entry->entry_state = INGRESS_RESOLVED; -+ return; /* Shortcut already open... */ ++ return; /* Shortcut already open... */ + } -+ if (entry->shortcut == NULL) { -+ entry->entry_state = INGRESS_RESOLVED; -+ msg->type = OPEN_INGRESS_SVC; -+ msg_to_mpoad(msg,client); -+ return; -+ } + -+ printk("mpoa: (%s) MPOA_res_reply_rcvd: still here, impossible!\n", client->dev->name); -+ return; ++ if (entry->shortcut != NULL) { ++ printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n", ++ client->dev->name); ++ return; ++ } ++ ++ /* entry->shortcut == NULL so we need to get a VC. First check for candicates ++ * in egress cache. If none found, ask daemon to create one. ++ */ ++ eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client); ++ if (eg_entry != NULL) { ++ ip = (unsigned char *)&dst_ip; ++ entry->shortcut = eg_entry->shortcut; ++ dprintk("mpoa: (%s) using egress SVC to reach %d.%d.%d.%d\n", ++ client->dev->name, ip[0], ip[1], ip[2], ip[3]); ++ ++ } ++ ++ /* It is possible that there was an egress entry with no valid shortcut */ ++ if (entry->shortcut == NULL) { ++ msg->type = OPEN_INGRESS_SVC; ++ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); ++ if (qos != NULL) { ++ msg->qos = qos->qos; ++ printk("mpoa: (%s) MPOA_res_reply_rcvd: trying to get a CBR shortcut\n", ++ client->dev->name); ++ } ++ msg_to_mpoad(msg, client); ++ } ++ ++ entry->entry_state = INGRESS_RESOLVED; ++ ++ return; ++ +} + +static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) @@ -14188,6 +14315,7 @@ +{ + extern struct atm_mpoa_ops atm_mpoa_ops; + struct mpoa_client *mpc, *tmp; ++ struct atm_mpoa_qos *qos, *nextqos; + struct lec_priv *priv; + + if (MOD_IN_USE) { @@ -14221,21 +14349,30 @@ + memset(mpc, 0, sizeof(struct mpoa_client)); + ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc); + kfree(mpc); -+ ddprintk("mpoa: cleanup_module: kfree() done\n"); + ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp); + mpc = tmp; + } + ++ qos = qos_head; ++ qos_head = NULL; ++ while (qos != NULL) { ++ nextqos = qos->next; ++ dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos); ++ kfree(qos); ++ qos = nextqos; ++ } ++ + return; +} +#endif /* MODULE */ + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpc.h Wed Aug 19 14:59:32 1998 -@@ -0,0 +1,59 @@ ++++ work/net/atm/mpc.h Wed Aug 19 18:49:00 1998 +@@ -0,0 +1,73 @@ +#ifndef _MPC_H_ +#define _MPC_H_ + ++#include +#include +#include +#include @@ -14251,23 +14388,29 @@ + +struct mpoa_client { + struct mpoa_client *next; -+ struct device *dev; /* lec in question */ -+ int dev_num; /* e.g. 2 for lec2 */ ++ struct device *dev; /* lec in question */ ++ int dev_num; /* e.g. 2 for lec2 */ + int (*old_hard_start_xmit)(struct sk_buff *skb, struct device *dev); -+ struct atm_vcc *mpoad_vcc; /* control channel to mpoad */ -+ uint8_t mps_ctrl_addr[ATM_ESA_LEN]; /* MPS control ATM address */ -+ uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */ ++ struct atm_vcc *mpoad_vcc; /* control channel to mpoad */ ++ uint8_t mps_ctrl_addr[ATM_ESA_LEN]; /* MPS control ATM address */ ++ uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */ + + rwlock_t ingress_lock; -+ struct in_cache_ops *in_ops; /* ingress cache operations */ -+ in_cache_entry *in_cache; /* the ingress cache of this MPC */ ++ struct in_cache_ops *in_ops; /* ingress cache operations */ ++ in_cache_entry *in_cache; /* the ingress cache of this MPC */ + + rwlock_t egress_lock; -+ struct eg_cache_ops *eg_ops; /* egress cache operations */ -+ eg_cache_entry *eg_cache; /* the egress cache of this MPC */ ++ struct eg_cache_ops *eg_ops; /* egress cache operations */ ++ eg_cache_entry *eg_cache; /* the egress cache of this MPC */ + -+ uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */ -+ int number_of_mps_macs; /* number of the above MAC addresses */ ++ uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */ ++ int number_of_mps_macs; /* number of the above MAC addresses */ ++}; ++ ++struct atm_mpoa_qos { ++ struct atm_mpoa_qos *next; ++ uint32_t ipaddr; ++ struct atm_qos qos; +}; + +/* TLVs this MPC recognizes */ @@ -14290,11 +14433,18 @@ +void atm_mpoa_init(void); +void atm_mpoa_init_ops(struct atm_mpoa_ops *ops); + -+#endif /* _MPC_H_ */ ++/* MPOA QoS operations */ ++struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos); ++struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip); ++int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos); + ++/* Display QoS entries. This is for the procfs */ ++void atm_mpoa_disp_qos(char *page, int *len); ++ ++#endif /* _MPC_H_ */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_caches.c Tue Aug 11 19:14:28 1998 -@@ -0,0 +1,507 @@ ++++ work/net/atm/mpoa_caches.c Wed Aug 19 18:49:00 1998 +@@ -0,0 +1,535 @@ +#include +#include +#include @@ -14397,6 +14547,7 @@ + +static int cache_hit( in_cache_entry * entry, struct mpoa_client *mpc) +{ ++ struct atm_mpoa_qos *qos; + struct k_message msg; + + entry->count++; @@ -14408,6 +14559,8 @@ + msg.type = SND_MPOA_RES_RTRY; + msg.content.in_info = entry->ctrl_info; + memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN); ++ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); ++ if (qos != NULL) msg.qos = qos->qos; + msg_to_mpoad(&msg, mpc); + do_gettimeofday(&(entry->reply_wait)); + entry->entry_state = INGRESS_RESOLVING; @@ -14429,6 +14582,8 @@ + msg.type = SND_MPOA_RES_RQST; + memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN ); + msg.content.in_info = entry->ctrl_info; ++ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); ++ if (qos != NULL) msg.qos = qos->qos; + msg_to_mpoad( &msg, mpc); + do_gettimeofday(&(entry->reply_wait)); + } @@ -14525,6 +14680,7 @@ +static void check_resolving_entries( struct mpoa_client * client ) +{ + ++ struct atm_mpoa_qos *qos; + unsigned long flags; + in_cache_entry *entry; + struct timeval now; @@ -14555,7 +14711,9 @@ + msg.type = SND_MPOA_RES_RTRY; + memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN); + msg.content.in_info = entry->ctrl_info; -+ msg_to_mpoad(&msg, client ); ++ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); ++ if (qos != NULL) msg.qos = qos->qos; ++ msg_to_mpoad(&msg, client); + do_gettimeofday(&(entry->reply_wait)); + } + } @@ -14651,6 +14809,25 @@ + return NULL; +} + ++static eg_cache_entry *eg_cache_search_by_src_ip(uint32_t ipaddr, ++ struct mpoa_client *client) ++{ ++ unsigned long flags; ++ eg_cache_entry *entry; ++ ++ read_lock_irqsave(&client->egress_lock, flags); ++ entry = client->eg_cache; ++ while( entry != NULL ){ ++ if(entry->latest_ip_addr == ipaddr) { ++ break; ++ } ++ entry = entry->next; ++ } ++ read_unlock_irqrestore(&client->egress_lock, flags); ++ ++ return entry; ++} ++ +/* + * If there are no more references to vcc in ingress cache, + * we are ready to close it. @@ -14761,7 +14938,7 @@ + msg.type = SND_EGRESS_PURGE; + msg.content.eg_info = entry->ctrl_info; + printk("mpoa: mpoa_caches.c: egress_cache:holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id)); -+ msg_to_mpoad(&msg,client); ++ msg_to_mpoad(&msg, client); + eg_cache_remove(entry, client); + } + entry = next_entry; @@ -14781,7 +14958,7 @@ + in_cache_remove, /* cache_remove */ + clear_count_and_expired, /* clear_count */ + check_resolving_entries, /* check_resolving */ -+ refresh_entries /* refresh */ ++ refresh_entries, /* refresh */ +}; + +static struct eg_cache_ops egress_ops = { @@ -14789,6 +14966,7 @@ + eg_cache_search_by_cache_id, /* search_by_cache_id */ + eg_cache_search_by_tag, /* search_by_tag */ + eg_cache_search_by_vcc, /* search_by_vcc */ ++ eg_cache_search_by_src_ip, /* search_by_src_ip */ + eg_cache_remove, /* cache_remove */ + update_eg_cache_entry, /* update */ + clear_expired /* clear_expired */ @@ -14803,7 +14981,7 @@ + return; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_caches.h Wed Aug 19 14:59:32 1998 ++++ work/net/atm/mpoa_caches.h Wed Aug 19 18:49:00 1998 @@ -0,0 +1,87 @@ +#ifndef MPOA_CACHES_H +#define MPOA_CACHES_H @@ -14814,8 +14992,6 @@ +#include +#include + -+ -+ +struct mpoa_client; + +void atm_mpoa_init_cache(struct mpoa_client *mpc); @@ -14859,6 +15035,7 @@ + struct atm_vcc *shortcut; + uint32_t packets_rcvd; + uint16_t entry_state; ++ uint32_t latest_ip_addr; /* The src IP address of the last packet */ + struct eg_ctrl_info ctrl_info; +} eg_cache_entry; + @@ -14867,6 +15044,7 @@ + eg_cache_entry *(*search_by_cache_id)(uint32_t cache_id, struct mpoa_client *client); + eg_cache_entry *(*search_by_tag)(uint32_t cache_id, struct mpoa_client *client); + eg_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client); ++ eg_cache_entry *(*search_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client); + int (*cache_remove)(eg_cache_entry *entry, struct mpoa_client *client); + void (*update)(eg_cache_entry *entry, uint16_t holding_time); + void (*clear_expired)(struct mpoa_client *client); @@ -14893,8 +15071,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_proc.c Wed Aug 12 19:27:54 1998 -@@ -0,0 +1,223 @@ ++++ work/net/atm/mpoa_proc.c Wed Aug 19 18:49:00 1998 +@@ -0,0 +1,393 @@ +#include + +#ifdef CONFIG_PROC_FS @@ -14906,6 +15084,7 @@ +#include +#include +#include ++#include +#include "mpc.h" +#include "mpoa_caches.h" + @@ -14914,6 +15093,12 @@ + * file system statistics + */ + ++#if 1 ++#define dprintk printk /* debug */ ++#else ++#define dprintk(format,args...) ++#endif ++ +#define STAT_FILE_NAME "mpc" /* Our statistic file's name */ + +extern struct mpoa_client *mpcs; @@ -14922,13 +15107,18 @@ +static ssize_t proc_mpc_read(struct file *file, char *buff, + size_t count, loff_t *pos); + ++static ssize_t proc_mpc_write(struct file *file, const char *buff, ++ size_t nbytes, loff_t *ppos); ++ ++static int parse_qos(const char *buff, int len); ++ +/* + * Define allowed FILE OPERATIONS + */ +static struct file_operations mpc_file_operations = { + NULL, /* lseek */ + proc_mpc_read, /* read */ -+ NULL, /* write */ ++ proc_mpc_write, /* write */ + NULL, /* readdir */ + NULL, /* poll - default */ + NULL, /* ioctl - default */ @@ -15047,7 +15237,8 @@ + return 0; + page = get_free_page(GFP_KERNEL); + if(!page) -+ return -ENOMEM; ++ return -ENOMEM; ++ atm_mpoa_disp_qos((char *)page, &length); + while(mpc != NULL){ + length += print_header((char *)page + length, mpc); + length += sprintf((char *)page + length,"Ingress Entries:\nIP-address State Holding_time Packets_fwded VPI VCI\n"); @@ -15063,13 +15254,19 @@ + } + length += sprintf((char *)page + length,"\n"); + eg_entry = mpc->eg_cache; -+ length += sprintf((char *)page + length,"Egress Entries:\nIngress_MPC_ATM_addr\nCache_id State Holding_time Packets_recvd VPI VCI\n"); ++ length += sprintf((char *)page + length,"Egress Entries:\nIngress_MPC_ATM_addr\nCache_id State Holding_time Packets_recvd Latest IP addr VPI VCI\n"); + while(eg_entry != NULL){ + for(i=0;ictrl_info.in_MPC_data_ATM_addr[i]);} -+ length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-12u",ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd); ++ length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-15u",ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd); ++ ++ /* latest IP address */ ++ temp = (unsigned char *)&eg_entry->latest_ip_addr; ++ sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); ++ length += sprintf((char *)page + length, "%-16s", ip_string); ++ + if(eg_entry->shortcut) -+ length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); ++ length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); + length += sprintf((char *)page + length,"\n"); + eg_entry = eg_entry->next; + } @@ -15086,6 +15283,157 @@ + + free_page(page); + return length; ++} ++ ++static ssize_t proc_mpc_write(struct file *file, const char *buff, ++ size_t nbytes, loff_t *ppos) ++{ ++ int incoming, error, retval; ++ char *page, c; ++ const char *tmp; ++ ++ if (nbytes < 0) return -EINVAL; ++ if (nbytes == 0) return 0; ++ if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1; ++ ++ error = verify_area(VERIFY_READ, buff, nbytes); ++ if (error) return error; ++ ++ page = (char *)__get_free_page(GFP_KERNEL); ++ if (page == NULL) return -ENOMEM; ++ ++ incoming = 0; ++ tmp = buff; ++ while(incoming < nbytes){ ++ if (get_user(c, tmp++)) return -EFAULT; ++ incoming++; ++ if (c == '\0' || c == '\n') ++ break; ++ } ++ ++ retval = copy_from_user(page, buff, incoming); ++ if (retval != 0) { ++ printk("mpoa: proc_mpc_write: copy_from_user() failed\n"); ++ return -EFAULT; ++ } ++ ++ *ppos += incoming; ++ ++ page[incoming] = '\0'; ++ retval = parse_qos(buff, incoming); ++ if (retval == 0) ++ printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); ++ ++ free_page((unsigned long)page); ++ ++ return nbytes; ++} ++ ++static int parse_qos(const char *buff, int len) ++{ ++ /* possible lines look like this ++ * add 130.230.54.142 tx=max_pcr,pcr,min_pcr,max_cdv,max_sdu rx=max_pcr,pcr,min_pcr,max_cdv,max_sd ++ */ ++ ++ int pos, i; ++ uint32_t ipaddr; ++ unsigned char ip[4]; ++ char cmd[4], temp[256]; ++ const char *tmp, *prev; ++ struct atm_qos qos; ++ int value[5]; ++ ++ pos = 0; ++ strncpy(cmd, buff, 3); ++ if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3)) ++ return 0; /* not add or del */ ++ ++ pos += 4; ++ /* next parse ip */ ++ prev = buff + pos; ++ for (i = 0; i < 3; i++) { ++ tmp = strchr(prev, '.'); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ ip[i] = (char)simple_strtoul(temp, NULL, 0); ++ tmp ++; ++ prev = tmp; ++ } ++ tmp = strchr(prev, ' '); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ ip[i] = (char)simple_strtoul(temp, NULL, 0); ++ ipaddr = *(uint32_t *)ip; ++ ++ if(!strncmp(cmd, "del", 3)) ++ return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); ++ tmp = strstr(buff, "tx="); ++ if(tmp == NULL) return 0; ++ tmp += 3; ++ prev = tmp; ++ for( i = 0; i < 4; i++){ ++ tmp = strchr(prev, ','); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ value[i] = (int)simple_strtoul(temp, NULL, 0); ++ tmp ++; ++ prev = tmp; ++ } ++ tmp = strchr(prev, ' '); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ value[i] = (int)simple_strtoul(temp, NULL, 0); ++ qos.txtp.traffic_class = ATM_CBR; ++ qos.txtp.max_pcr = value[0]; ++ qos.txtp.pcr = value[1]; ++ qos.txtp.min_pcr = value[2]; ++ qos.txtp.max_cdv = value[3]; ++ qos.txtp.max_sdu = value[4]; ++ ++ tmp = strstr(buff, "rx="); ++ if(tmp == NULL) return 0; ++ tmp += 3; ++ prev = tmp; ++ for( i = 0; i < 4; i++){ ++ tmp = strchr(prev, ','); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ value[i] = (int)simple_strtoul(temp, NULL, 0); ++ tmp ++; ++ prev = tmp; ++ } ++ tmp = strchr(prev, '\0'); ++ if (tmp == NULL) return 0; ++ memset(temp, '\0', 256); ++ memcpy(temp, prev, tmp-prev); ++ value[i] = (int)simple_strtoul(temp, NULL, 0); ++ qos.rxtp.traffic_class = ATM_CBR; ++ qos.rxtp.max_pcr = value[0]; ++ qos.rxtp.pcr = value[1]; ++ qos.rxtp.min_pcr = value[2]; ++ qos.rxtp.max_cdv = value[3]; ++ qos.rxtp.max_sdu = value[4]; ++ dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d,%d,%d,%d rx=%d,%d,%d,%d,%d\n", ++ qos.txtp.max_pcr, ++ qos.txtp.pcr, ++ qos.txtp.min_pcr, ++ qos.txtp.max_cdv, ++ qos.txtp.max_sdu, ++ qos.rxtp.max_pcr, ++ qos.rxtp.pcr, ++ qos.rxtp.min_pcr, ++ qos.rxtp.max_cdv, ++ qos.rxtp.max_sdu ++ ); ++ ++ qos.aal = ATM_AAL5; ++ atm_mpoa_add_qos(ipaddr, &qos); ++ return 1; +} + +/* diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex --- old/atm/doc/usage.tex Wed Aug 19 16:41:03 1998 +++ new/atm/doc/usage.tex Wed Aug 19 19:03:36 1998 @@ -1,7 +1,7 @@ %%def%:= %:\begin{verbatim} -%:Usage instructions - ATM on Linux, release 0.41 +%:Usage instructions - ATM on Linux, release 0.42 %:------------------------------------------------- %: %:\end{verbatim} @@ -38,7 +38,7 @@ \title{ATM on Linux \\ User's guide \\ - Release 0.41 (alpha)} + Release 0.42 (alpha)} \author{Werner Almesberger \\ {\tt Werner.Almesberger@epfl.ch} \\ \\ @@ -81,7 +81,7 @@ In order to install this package, you need \begin{itemize} \item the package itself - \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.41.tar.gz} + \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.42.tar.gz} \item the Linux kernel, version 2.1.105, e.g. from \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz} \item Perl, version 4 or 5 @@ -98,7 +98,7 @@ distribution: \begin{verbatim} -tar xfz atm-0.41.tar.gz +tar xfz atm-0.42.tar.gz \end{verbatim} and the kernel source: diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt --- old/atm/doc/usage.txt Wed Aug 19 16:45:55 1998 +++ new/atm/doc/usage.txt Wed Aug 19 19:04:05 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.41 +Usage instructions - ATM on Linux, release 0.42 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,7 +17,7 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.41.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.42.tar.gz - the Linux kernel, version 2.1.105, e.g. from ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz - Perl, version 4 or 5 @@ -33,7 +33,7 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.41.tar.gz +tar xfz atm-0.42.tar.gz and the kernel source: .