diff -ur --new-file old/linux/include/linux/atmmpc.h new/linux/include/linux/atmmpc.h --- old/linux/include/linux/atmmpc.h Sat Dec 5 02:10:46 1998 +++ new/linux/include/linux/atmmpc.h Sat Dec 5 02:11:36 1998 @@ -37,6 +37,15 @@ uint16_t holding_time; } eg_ctrl_info; +struct mpc_parameters{ + uint16_t mpc_p1; /* Shortcut-Setup Frame Count */ + uint16_t mpc_p2; /* Shortcut-Setup Frame Time */ + uint8_t mpc_p3[8]; /* Flow-detection Protocols */ + uint16_t mpc_p4; /* MPC Initial Retry Time */ + uint16_t mpc_p5; /* MPC Retry Time Maximum */ + uint16_t mpc_p6; /* Hold Down Time */ +}; + struct k_message{ uint16_t type; uint32_t ip_mask; @@ -44,6 +53,7 @@ union { in_ctrl_info in_info; eg_ctrl_info eg_info; + struct mpc_parameters params; } content; struct atm_qos qos; } k_message; @@ -56,6 +66,16 @@ uint8_t type[2]; /* Ether type (for IP) (0x0800) */ }; +/* TLVs this MPC recognizes */ +#define TLV_MPOA_DEVICE_TYPE 0x00a03e2a + +/* MPOA device types in MPOA Device Type TLV */ +#define NON_MPOA 0 +#define MPS 1 +#define MPC 2 +#define MPS_AND_MPC 3 + + /* MPC parameter defaults */ #define MPC_P1 10 /* Shortcut-Setup Frame Count */ @@ -75,11 +95,11 @@ #define SND_MPOA_RES_RQST 201 #define SET_MPS_CTRL_ADDR 202 -#define SND_MPOA_RES_RTRY 203 /* Different type in a retry due to req id.*/ +#define SND_MPOA_RES_RTRY 203 /* Different type in a retry due to req id */ #define STOP_KEEP_ALIVE_SM 204 #define EGRESS_ENTRY_REMOVED 205 #define SND_EGRESS_PURGE 206 -#define DIE 207 +#define DIE 207 /* tell the daemon to exit() */ #define DATA_PLANE_PURGE 208 /* Data plane purge because of egress cache hit miss or dead MPS */ #define OPEN_INGRESS_SVC 209 @@ -91,9 +111,14 @@ #define EGRESS_PURGE_RCVD 104 #define MPS_DEATH 105 #define CACHE_IMPOS_RCVD 106 -#define SET_MPC_CTRL_ADDR 107 /* Our MPC's control ATM address */ +#define SET_MPC_CTRL_ADDR 107 /* Our MPC's control ATM address */ #define SET_MPS_MAC_ADDR 108 #define CLEAN_UP_AND_EXIT 109 - +#define SET_MPC_PARAMS 110 /* MPC configuration parameters */ + +/* Message types - bidirectional */ + +#define RELOAD 301 /* kill -HUP the daemon for reload */ + #endif /* _ATMMPC_H_ */ diff -ur --new-file old/linux/net/atm/lec.c new/linux/net/atm/lec.c --- old/linux/net/atm/lec.c Sat Dec 5 02:10:47 1998 +++ new/linux/net/atm/lec.c Sat Dec 5 02:11:37 1998 @@ -120,6 +120,7 @@ if (!priv->lecd) { printk("%s:No lecd attached\n",dev->name); priv->stats.tx_errors++; + dev->tbusy = 1; return -EUNATCH; } if (dev->tbusy) { @@ -568,6 +569,15 @@ return 0; } +/* shamelessly stolen from drivers/net/net_init.c */ +static int lec_change_mtu(struct device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > 18190)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + static int lec_init(struct device *dev) { @@ -578,6 +588,7 @@ memset(dev->priv,0,sizeof(struct lec_priv)); ether_setup(dev); + dev->change_mtu = lec_change_mtu; dev->hard_header = lec_hard_header; dev->rebuild_header = lec_rebuild_header; dev->hard_header_cache = NULL; diff -ur --new-file old/linux/net/atm/mpc.c new/linux/net/atm/mpc.c --- old/linux/net/atm/mpc.c Sat Dec 5 02:10:47 1998 +++ new/linux/net/atm/mpc.c Sat Dec 5 02:11:37 1998 @@ -56,11 +56,13 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void mps_death(struct k_message *msg, struct mpoa_client *mpc); -static void clean_up(struct k_message *msg, struct mpoa_client *mpc); +static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action); static void MPOA_cache_impos_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc); static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc); +static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac, + uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type); 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); @@ -348,7 +350,7 @@ } /* - * lec device calls this via its dev->priv->lan2_ops->associate_indicator() + * lec device calls this via its dev->priv->lane2_ops->associate_indicator() * when it sees a TLV in LE_ARP packet. * We fill in the pointer above when we see a LANE2 lec initializing * See LANE2 spec 3.1.5 @@ -383,37 +385,6 @@ printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name); return; } - /* Sampo-Add: start */ - switch(type){ - case TLV_SC_SETUP_FRAME_COUNT: - mpc->parameters.mpc_p1 = (*(tlvs+1)<<8) | (*tlvs); - printk("mpoa: lane2_assoc_ind(): MPC_p1 = %d\n",mpc->parameters.mpc_p1); - break; - case TLV_SC_SETUP_FRAME_TIME: - mpc->parameters.mpc_p2 = (*(tlvs+1)<<8) | (*tlvs); - printk("mpoa: lane2_assoc_ind(): MPC_p2 = %d\n",mpc->parameters.mpc_p2); - break; - case TLV_FLOW_DETECTION_PROTOCOLS: - memcpy(mpc->parameters.mpc_p3, tlvs, length); - printk("mpoa: lane2_assoc_ind(): MPC_p3 = %s\n",mpc->parameters.mpc_p3); - break; - case TLV_MPC_ININTIAL_RETRY_TIME: - mpc->parameters.mpc_p4 = (*(tlvs+1)<<8) | (*tlvs); - printk("mpoa: lane2_assoc_ind(): MPC_p4 = %d\n",mpc->parameters.mpc_p4); - break; - case TLV_MPC_RETRY_TIME_MAXIMUM: - mpc->parameters.mpc_p5 = (*(tlvs+1)<<8) | (*tlvs); - printk("mpoa: lane2_assoc_ind(): MPC_p5 = %d\n",mpc->parameters.mpc_p5); - break; - case TLV_HOLD_DOWN_TIME: - mpc->parameters.mpc_p6 = (*(tlvs+1)<<8) | (*tlvs); - printk("mpoa: lane2_assoc_ind(): MPC_p6 = %d\n",mpc->parameters.mpc_p6); - break; - default: - break; - - } - /* Sampo-Add: end */ if (type != TLV_MPOA_DEVICE_TYPE) { tlvs += length; @@ -448,25 +419,8 @@ /* ok, now we can go and tell our daemon the control address of MPS */ send_set_mps_ctrl_addr(tlvs, mpc); - tlvs += 20; if (mpoa_device_type == MPS_AND_MPC) tlvs += 20; - /* collect the MPS MAC addresses */ - if (mpc->number_of_mps_macs < number_of_mps_macs) { - kfree(mpc->mps_macs); /* need more space */ - mpc->mps_macs = kmalloc(number_of_mps_macs*ETH_ALEN, GFP_KERNEL); - if (mpc->mps_macs == NULL) { - printk("mpoa: (%s) lane2_assoc_ind: out of mem\n", dev->name); - return; - } - } - - /* be careful not to zero out any command line MACs */ - if (number_of_mps_macs > 0) { - mpc->number_of_mps_macs = number_of_mps_macs; - while (number_of_mps_macs > 0) { - memcpy(mpc->mps_macs, tlvs, ETH_ALEN); - tlvs += ETH_ALEN; number_of_mps_macs--; - } - } + tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type); + if (tlvs == NULL) return; } if (end_of_tlvs - tlvs != 0) printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n", @@ -474,6 +428,41 @@ return; } +/* + * store either advertizing router's MAC address + * or the MAC address(es) in this TLV + */ +static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac, + uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type) +{ + int num_macs; + num_macs = (mps_macs > 1) ? mps_macs : 1; + + if (mpc->number_of_mps_macs != num_macs) { + kfree(mpc->mps_macs); + mpc->number_of_mps_macs = num_macs; + mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL); + if (mpc->mps_macs == NULL) { + printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name); + return NULL; + } + } + + /* copy the advertizing routers MAC address */ + memcpy(mpc->mps_macs, router_mac, ETH_ALEN); + + tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20; + /* + * collect the MPS MAC addresses. + * however, it is possible that TLV includes no MACs + */ + if (mps_macs > 0) + memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN); + tlvs += mps_macs*ETH_ALEN; + + return tlvs; +} + /* FIXME: tarvitsee työtä */ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) { @@ -940,8 +929,16 @@ break; case CLEAN_UP_AND_EXIT: printk(" clean_up_and_exit\n"); - clean_up(mesg, mpc); + clean_up(mesg, mpc, DIE); break; + case RELOAD: + printk(" reload\n"); + clean_up(mesg, mpc, RELOAD); + break; + case SET_MPC_PARAMS: + printk(" set_mpc_params\n"); + mpc->parameters = mesg->content.params; + break; default: printk(" unknown message %d\n", mesg->type); break; @@ -1086,14 +1083,47 @@ return; } +/* + * Things get complicated because we have to check if there's an egress + * shortcut with suitable traffic parameters we could use. + */ +static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry){ + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + unsigned char *ip = (unsigned char *)&dst_ip; + struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); + eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client); + if(eg_entry && eg_entry->shortcut){ + if(eg_entry->shortcut->qos.txtp.traffic_class & + msg->qos.txtp.traffic_class & + (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){ + if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR) + entry->shortcut = eg_entry->shortcut; + else if(eg_entry->shortcut->qos.txtp.max_pcr > 0) + entry->shortcut = eg_entry->shortcut; + } + if(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]); + return; + } + } + /* No luck in the egress cache we must open an ingress SVC */ + msg->type = OPEN_INGRESS_SVC; + if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) + { + msg->qos = qos->qos; + printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name); + } + else memset(&msg->qos,0,sizeof(struct atm_qos)); + msg_to_mpoad(msg, client); + return; +} + 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; - 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); @@ -1124,6 +1154,9 @@ client->dev->name); return; } + + check_qos_and_open_shortcut(msg, client, entry); +#if 0 /* 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. @@ -1143,7 +1176,7 @@ msg->type = OPEN_INGRESS_SVC; qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); if (qos != NULL && qos->qos.txtp.traffic_class & msg->qos.txtp.traffic_class) { - msg->qos = qos->qos; + msg->qos = qos->qos; printk("mpoa: (%s) MPOA_res_reply_rcvd: trying to get a CBR shortcut\n", client->dev->name); } @@ -1153,7 +1186,8 @@ } msg_to_mpoad(msg, client); } - +#endif + entry->entry_state = INGRESS_RESOLVED; return; @@ -1343,7 +1377,10 @@ return; } -static void clean_up(struct k_message *msg, struct mpoa_client *mpc){ +/* + * purge egress cache and tell daemon to 'action' (DIE, RELOAD) + */ +static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action){ unsigned long flags; eg_cache_entry *entry; @@ -1360,7 +1397,7 @@ } read_unlock_irqrestore(&mpc->egress_lock, flags); - msg->type = DIE; + msg->type = action; msg_to_mpoad(msg, mpc); return; } @@ -1480,6 +1517,3 @@ return; } #endif /* MODULE */ - - - diff -ur --new-file old/linux/net/atm/mpc.h new/linux/net/atm/mpc.h --- old/linux/net/atm/mpc.h Sat Dec 5 02:10:47 1998 +++ new/linux/net/atm/mpc.h Sat Dec 5 02:11:37 1998 @@ -14,15 +14,6 @@ int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg); int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg); -struct mpc_parameters{ - uint16_t mpc_p1; /* Shortcut-Setup Frame Count */ - uint16_t mpc_p2; /* Shortcut-Setup Frame Time */ - uint8_t mpc_p3[8]; /* Flow-detection Protocols */ - uint16_t mpc_p4; /* MPC Initial Retry Time */ - uint16_t mpc_p5; /* MPC Retry Time Maximum */ - uint16_t mpc_p6; /* Hold Down Time */ -}; - struct mpoa_client { struct mpoa_client *next; struct device *dev; /* lec in question */ @@ -51,21 +42,6 @@ uint32_t ipaddr; struct atm_qos qos; }; - -/* TLVs this MPC recognizes */ -#define TLV_MPOA_DEVICE_TYPE 0x00a03e2a -#define TLV_SC_SETUP_FRAME_COUNT 0x00a03e24 /* MPC_p1 */ -#define TLV_SC_SETUP_FRAME_TIME 0x00a03e25 /* MPC_p2 */ -#define TLV_FLOW_DETECTION_PROTOCOLS 0x00a03e26 /* MPC_p3 */ -#define TLV_MPC_ININTIAL_RETRY_TIME 0x00a03e27 /* MPC_p4 */ -#define TLV_MPC_RETRY_TIME_MAXIMUM 0x00a03e28 /* MPC_p5 */ -#define TLV_HOLD_DOWN_TIME 0x00a03e29 /* MPC_p6 */ - -/* MPOA device types in MPOA Device Type TLV */ -#define NON_MPOA 0 -#define MPS 1 -#define MPC 2 -#define MPS_AND_MPC 3 /* Functions to call during ioctl(ATMMPC, ) */ diff -ur --new-file old/linux/net/atm/mpoa_caches.c new/linux/net/atm/mpoa_caches.c --- old/linux/net/atm/mpoa_caches.c Sat Dec 5 02:10:47 1998 +++ new/linux/net/atm/mpoa_caches.c Sat Dec 5 02:11:37 1998 @@ -130,7 +130,7 @@ if(entry->entry_state == INGRESS_REFRESHING){ if(entry->count > mpc->parameters.mpc_p1){ - msg.type = SND_MPOA_RES_RTRY; + msg.type = SND_MPOA_RES_RQST; 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); .