diff -ur --new-file old/linux/include/linux/atmmpc.h new/linux/include/linux/atmmpc.h --- old/linux/include/linux/atmmpc.h Fri Oct 30 20:14:00 1998 +++ new/linux/include/linux/atmmpc.h Fri Oct 30 20:14:46 1998 @@ -45,7 +45,7 @@ in_ctrl_info in_info; eg_ctrl_info eg_info; } content; - struct atm_qos qos; /* only used with content.in_info */ + struct atm_qos qos; } k_message; struct llc_snap_hdr { /* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */ diff -ur --new-file old/linux/include/linux/atmsap.h new/linux/include/linux/atmsap.h --- old/linux/include/linux/atmsap.h Fri Oct 30 20:14:00 1998 +++ new/linux/include/linux/atmsap.h Fri Oct 30 20:14:46 1998 @@ -95,7 +95,7 @@ * SAP structures */ -#define ATM_MAX_HLI 7 /* maximum high-layer information length */ +#define ATM_MAX_HLI 8 /* maximum high-layer information length */ struct atm_blli { diff -ur --new-file old/linux/net/atm/common.c new/linux/net/atm/common.c --- old/linux/net/atm/common.c Fri Oct 30 20:14:01 1998 +++ new/linux/net/atm/common.c Fri Oct 30 20:14:46 1998 @@ -729,7 +729,7 @@ if (error) return error; break; case ATM_GETCIRANGE: - size = sizeof(sizeof(struct atm_cirange)); + size = sizeof(struct atm_cirange); if (copy_to_user(buf,&dev->ci_range,size)) return -EFAULT; break; diff -ur --new-file old/linux/net/atm/mpc.c new/linux/net/atm/mpc.c --- old/linux/net/atm/mpc.c Fri Oct 30 20:14:01 1998 +++ new/linux/net/atm/mpc.c Fri Oct 30 20:14:47 1998 @@ -63,6 +63,7 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry); +static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc); static void mpoad_close(struct atm_vcc *vcc); static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb); @@ -151,12 +152,18 @@ */ /* - * Returns the new entry. Note the use of the 2nd argument + * Overwrites the old entry or makes a new one. */ struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos) { struct atm_mpoa_qos *entry; + entry = atm_mpoa_search_qos(dst_ip); + if (entry != NULL) { + entry->qos = *qos; + return entry; + } + entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL); if (entry == NULL) { printk("mpoa: atm_mpoa_add_qos: out of memory\n"); @@ -358,8 +365,6 @@ { uint32_t type; uint8_t length, mpoa_device_type, number_of_mps_macs; - struct k_message *mesg; - struct sk_buff *skb; uint8_t *end_of_tlvs; struct mpoa_client *mpc; @@ -441,17 +446,7 @@ printk("this MPS has %d MAC addresses\n", number_of_mps_macs); /* ok, now we can go and tell our daemon the control address of MPS */ - skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); - if (skb == NULL) { - printk("mpoa: (%s) lane2_assoc_ind: alloc_skb()\n", dev->name); - return; - } - memcpy (mpc->mps_ctrl_addr, tlvs, ATM_ESA_LEN); - - mesg = (struct k_message *)skb->data; - mesg->type = SET_MPS_CTRL_ADDR; - memcpy(mesg->MPS_ctrl, tlvs, ATM_ESA_LEN); - msg_to_mpoad(mesg, mpc); + send_set_mps_ctrl_addr(tlvs, mpc); tlvs += 20; if (mpoa_device_type == MPS_AND_MPC) tlvs += 20; /* collect the MPS MAC addresses */ @@ -814,13 +809,43 @@ mpc->mpoad_vcc = vcc; bind_vcc(vcc, &mpc_dev); vcc->flags |= ATM_VF_READY | ATM_VF_META; - if (mpc->dev) + + if (mpc->dev) { + char empty[ATM_ESA_LEN]; + memset(empty, 0, ATM_ESA_LEN); + start_mpc(mpc, mpc->dev); - MOD_INC_USE_COUNT; + /* set address if mpcd e.g. gets killed and restarted. + * If we do not do it now we have to wait for the next LE_ARP + */ + if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 ) + send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); + } + MOD_INC_USE_COUNT; return arg; } +static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc) +{ + struct sk_buff *skb; + struct k_message *mesg; + + skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); + if (skb == NULL) { + printk("mpoa: (%s) lane2_assoc_ind: alloc_skb()\n", mpc->dev->name); + return; + } + memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN); + + mesg = (struct k_message *)skb->data; + mesg->type = SET_MPS_CTRL_ADDR; + memcpy(mesg->MPS_ctrl, addr, ATM_ESA_LEN); + msg_to_mpoad(mesg, mpc); + + return; +} + static void mpoad_close(struct atm_vcc *vcc) { unsigned long flags; @@ -1104,23 +1129,28 @@ * 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]); - + if (eg_entry != NULL && eg_entry->shortcut) { + /* FIXME: Is it enough to just look at the max_pcr-value? */ + if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR || (eg_entry->shortcut->qos.txtp.traffic_class == ATM_CBR && eg_entry->shortcut->qos.txtp.max_pcr > 0)){ + entry->shortcut = eg_entry->shortcut; + ip = (unsigned char *)&dst_ip; + 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) { + if (qos != NULL && qos->qos.txtp.traffic_class & msg->qos.txtp.traffic_class) { msg->qos = qos->qos; printk("mpoa: (%s) MPOA_res_reply_rcvd: trying to get a CBR shortcut\n", client->dev->name); } + else{ + if(qos)printk("mpoa: (%s) requested qos-parameters not supported by the other end\n",client->dev->name); + memset(&msg->qos,0,sizeof(struct atm_qos)); + } msg_to_mpoad(msg, client); } diff -ur --new-file old/linux/net/atm/mpoa_proc.c new/linux/net/atm/mpoa_proc.c --- old/linux/net/atm/mpoa_proc.c Fri Oct 30 20:14:01 1998 +++ new/linux/net/atm/mpoa_proc.c Fri Oct 30 20:14:47 1998 @@ -257,7 +257,7 @@ 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 + * add 130.230.54.142 tx=max_pcr,max_cdv,max_sdu rx=max_pcr,max_cdv,max_sdu */ int pos, i; @@ -268,12 +268,12 @@ struct atm_qos qos; int value[5]; - pos = 0; + memset(&qos, 0, sizeof(struct atm_qos)); strncpy(cmd, buff, 3); - if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3)) + if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3)) return 0; /* not add or del */ - pos += 4; + pos = 4; /* next parse ip */ prev = buff + pos; for (i = 0; i < 3; i++) { @@ -294,11 +294,13 @@ if(!strncmp(cmd, "del", 3)) return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); + + /* next transmit values */ tmp = strstr(buff, "tx="); if(tmp == NULL) return 0; tmp += 3; prev = tmp; - for( i = 0; i < 4; i++){ + for( i = 0; i < 2; i++){ tmp = strchr(prev, ','); if (tmp == NULL) return 0; memset(temp, '\0', 256); @@ -314,16 +316,15 @@ 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]; + qos.txtp.max_cdv = value[1]; + qos.txtp.max_sdu = value[2]; + /* next receive values */ tmp = strstr(buff, "rx="); if(tmp == NULL) return 0; tmp += 3; prev = tmp; - for( i = 0; i < 4; i++){ + for( i = 0; i < 2; i++){ tmp = strchr(prev, ','); if (tmp == NULL) return 0; memset(temp, '\0', 256); @@ -339,19 +340,13 @@ 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.rxtp.max_cdv = value[1]; + qos.rxtp.max_sdu = value[2]; + dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d,%d rx=%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 ); diff -ur --new-file old/linux/net/sched/sch_atm.c new/linux/net/sched/sch_atm.c --- old/linux/net/sched/sch_atm.c Fri Oct 30 20:14:01 1998 +++ new/linux/net/sched/sch_atm.c Fri Oct 30 20:14:46 1998 @@ -95,6 +95,17 @@ } +static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch, + u32 classid) +{ + struct atm_flow_data *flow; + + for (flow = PRIV(sch)->flows; flow; flow = flow->next) + if (flow->classid == classid) break; + return flow; +} + + static int atm_tc_graft(struct Qdisc *sch,unsigned long arg, struct Qdisc *new,struct Qdisc **old) { @@ -106,6 +117,7 @@ if (!find_flow(p,flow)) return -EINVAL; if (!new) new = &noop_qdisc; *old = xchg(&flow->q,new); + if (*old) qdisc_reset(*old); return 0; } @@ -113,11 +125,10 @@ static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid) { struct atm_qdisc_data *p = PRIV(sch); - struct atm_flow_data *flow; + struct atm_flow_data *flow; DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid); - for (flow = PRIV(sch)->flows; flow; flow = flow->next) - if (flow->classid == classid) break; + flow = lookup_flow(sch,classid); if (flow) flow->ref++; DPRINTK("atm_tc_get: flow %p\n",flow); return (unsigned long) flow; @@ -329,7 +340,7 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) { struct atm_qdisc_data *p = PRIV(sch); - struct atm_flow_data *flow; + struct atm_flow_data *flow = NULL ; /* @@@ */ struct tcf_result res; int result; @@ -341,7 +352,10 @@ if (flow->filter_list) { result = tc_classify(skb,flow->filter_list, &res); - if (result >= 0) break; + if (result < 0) continue; + flow = (struct atm_flow_data *) res.class; + if (!flow) flow = lookup_flow(sch,res.classid); + break; } if (!flow) flow = &p->link; else { @@ -366,8 +380,8 @@ default: break; } - } #endif + } if ( #ifdef CONFIG_NET_CLS_POLICE result == TC_POLICE_SHOT || @@ -480,10 +494,6 @@ DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); /* races ? */ while ((flow = p->flows)) { - struct tcf_proto *filter; - - for (filter = flow->filter_list; filter; filter = filter->next) - filter->ops->destroy(filter); if (flow->ref > 1) printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, flow->ref); .