/* * 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; struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); eg_cache_entry *eg_entry = client->eg_ops->get_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 %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip)); client->eg_ops->put(eg_entry); return; } } if (eg_entry != NULL) client->eg_ops->put(eg_entry); /* 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 int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc) { struct atm_mpoa_qos *qos; struct k_message msg; entry->count++; if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL) return OPEN; if (entry->entry_state == INGRESS_REFRESHING) { if (entry->count > mpc->parameters.mpc_p1) { 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); if (qos != NULL) msg.qos = qos->qos; msg_to_mpoad(&msg, mpc); do_gettimeofday(&(entry->reply_wait)); entry->entry_state = INGRESS_RESOLVING; } if (entry->shortcut != NULL) return OPEN; return CLOSED; } if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) return OPEN; if (entry->count > mpc->parameters.mpc_p1 && entry->entry_state == INGRESS_INVALID) { dprintk("(%s) threshold exceeded for ip %pI4, sending MPOA res req\n", mpc->dev->name, &entry->ctrl_info.in_dst_ip); entry->entry_state = INGRESS_RESOLVING; 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)); } return CLOSED; }
/* Call this every MPC-p4 seconds. */ static void check_resolving_entries(struct mpoa_client *client) { struct atm_mpoa_qos *qos; in_cache_entry *entry; struct timeval now; struct k_message msg; do_gettimeofday(&now); read_lock_bh(&client->ingress_lock); entry = client->in_cache; while (entry != NULL) { if (entry->entry_state == INGRESS_RESOLVING) { if ((now.tv_sec - entry->hold_down.tv_sec) < client->parameters.mpc_p6) { entry = entry->next; /* Entry in hold down */ continue; } if ((now.tv_sec - entry->reply_wait.tv_sec) > entry->retry_time) { entry->retry_time = MPC_C1 * (entry->retry_time); /* * Retry time maximum exceeded, * put entry in hold down. */ if (entry->retry_time > client->parameters.mpc_p5) { do_gettimeofday(&(entry->hold_down)); entry->retry_time = client->parameters.mpc_p4; entry = entry->next; continue; } /* Ask daemon to send a resolution request. */ memset(&(entry->hold_down), 0, sizeof(struct timeval)); msg.type = SND_MPOA_RES_RTRY; memcpy(msg.MPS_ctrl, client->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, client); do_gettimeofday(&(entry->reply_wait)); } } entry = entry->next; } read_unlock_bh(&client->ingress_lock); }
static int parse_qos(const char *buff) { /* possible lines look like this * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu */ unsigned char ip[4]; int tx_pcr, tx_sdu, rx_pcr, rx_sdu; uint32_t ipaddr; struct atm_qos qos; memset(&qos, 0, sizeof(struct atm_qos)); if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu", ip, ip+1, ip+2, ip+3) == 4) { ipaddr = *(uint32_t *)ip; return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); } if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx", ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) { rx_pcr = tx_pcr; rx_sdu = tx_sdu; } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d", ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8) return 0; ipaddr = *(uint32_t *)ip; qos.txtp.traffic_class = ATM_CBR; qos.txtp.max_pcr = tx_pcr; qos.txtp.max_sdu = tx_sdu; qos.rxtp.traffic_class = ATM_CBR; qos.rxtp.max_pcr = rx_pcr; qos.rxtp.max_sdu = rx_sdu; qos.aal = ATM_AAL5; dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", qos.txtp.max_pcr, qos.txtp.max_sdu, qos.rxtp.max_pcr, qos.rxtp.max_sdu ); atm_mpoa_add_qos(ipaddr, &qos); return 1; }
static int parse_qos(const char *buff) { /* */ unsigned char ip[4]; int tx_pcr, tx_sdu, rx_pcr, rx_sdu; __be32 ipaddr; struct atm_qos qos; memset(&qos, 0, sizeof(struct atm_qos)); if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu", ip, ip+1, ip+2, ip+3) == 4) { ipaddr = *(__be32 *)ip; return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); } if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx", ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) { rx_pcr = tx_pcr; rx_sdu = tx_sdu; } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d", ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8) return 0; ipaddr = *(__be32 *)ip; qos.txtp.traffic_class = ATM_CBR; qos.txtp.max_pcr = tx_pcr; qos.txtp.max_sdu = tx_sdu; qos.rxtp.traffic_class = ATM_CBR; qos.rxtp.max_pcr = rx_pcr; qos.rxtp.max_sdu = rx_sdu; qos.aal = ATM_AAL5; dprintk("parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", qos.txtp.max_pcr, qos.txtp.max_sdu, qos.rxtp.max_pcr, qos.rxtp.max_sdu); atm_mpoa_add_qos(ipaddr, &qos); return 1; }
/* * 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_mpoa_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; }
static int parse_qos(const char *buff, int len) { /* possible lines look like this * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu */ 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]; memset(&qos, 0, sizeof(struct atm_qos)); 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)); /* next transmit values */ tmp = strstr(buff, "tx="); if(tmp == NULL) return 0; tmp += 3; prev = tmp; for( i = 0; i < 1; 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.max_sdu = value[1]; /* next receive values */ tmp = strstr(buff, "rx="); if(tmp == NULL) return 0; if (strstr(buff, "rx=tx")) { /* rx == tx */ qos.rxtp.traffic_class = qos.txtp.traffic_class; qos.rxtp.max_pcr = qos.txtp.max_pcr; qos.rxtp.max_cdv = qos.txtp.max_cdv; qos.rxtp.max_sdu = qos.txtp.max_sdu; } else { tmp += 3; prev = tmp; for( i = 0; i < 1; 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.max_sdu = value[1]; } qos.aal = ATM_AAL5; dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", qos.txtp.max_pcr, qos.txtp.max_sdu, qos.rxtp.max_pcr, qos.rxtp.max_sdu ); atm_mpoa_add_qos(ipaddr, &qos); return 1; }