示例#1
0
static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
	uint32_t dst_ip = msg->content.in_info.in_dst_ip;
	in_cache_entry *entry;

	entry = mpc->in_ops->get(dst_ip, mpc);
	if(entry == NULL){
		entry = mpc->in_ops->add_entry(dst_ip, mpc);
		entry->entry_state = INGRESS_RESOLVING;
		msg->type = SND_MPOA_RES_RQST;
		msg->content.in_info = entry->ctrl_info;
		msg_to_mpoad(msg, mpc);
		do_gettimeofday(&(entry->reply_wait));
		mpc->in_ops->put(entry);
		return;
	}
	
	if(entry->entry_state == INGRESS_INVALID){
		entry->entry_state = INGRESS_RESOLVING;
		msg->type = SND_MPOA_RES_RQST;
		msg->content.in_info = entry->ctrl_info;
		msg_to_mpoad(msg, mpc);
		do_gettimeofday(&(entry->reply_wait));
		mpc->in_ops->put(entry);
		return;
	}
	
	printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
		(mpc->dev) ? mpc->dev->name : "<unknown>");
	mpc->in_ops->put(entry);
	return;
}
示例#2
0
/*
 * 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;
}
示例#3
0
static void clear_expired(struct mpoa_client *client)
{
    eg_cache_entry *entry, *next_entry;
    struct timeval now;
    struct k_message msg;

    do_gettimeofday(&now);

    write_lock_irq(&client->egress_lock);
    entry = client->eg_cache;
    while(entry != NULL) {
        next_entry = entry->next;
        if((now.tv_sec - entry->tv.tv_sec)
                > entry->ctrl_info.holding_time) {
            msg.type = SND_EGRESS_PURGE;
            msg.content.eg_info = entry->ctrl_info;
            dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
            msg_to_mpoad(&msg, client);
            client->eg_ops->remove_entry(entry, client);
        }
        entry = next_entry;
    }
    write_unlock_irq(&client->egress_lock);

    return;
}
示例#4
0
/*
 * This should be called with write lock on
 */
static void eg_cache_remove_entry(eg_cache_entry *entry,
                                  struct mpoa_client *client)
{
    struct atm_vcc *vcc;
    struct k_message msg;

    vcc = entry->shortcut;
    dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
    if (entry->prev != NULL)
        entry->prev->next = entry->next;
    else
        client->eg_cache = entry->next;
    if (entry->next != NULL)
        entry->next->prev = entry->prev;
    client->eg_ops->put(entry);
    if(client->in_cache == NULL && client->eg_cache == NULL) {
        msg.type = STOP_KEEP_ALIVE_SM;
        msg_to_mpoad(&msg,client);
    }

    /* Check if the ingress side still uses this VCC */
    if (vcc != NULL) {
        in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
        if (in_entry != NULL) {
            client->in_ops->put(in_entry);
            return;
        }
        vcc_release_async(vcc, -EPIPE);
    }

    return;
}
示例#5
0
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;
}
示例#6
0
static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc)
{
	struct k_message mesg;

	memcpy(mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);

	mesg.type = SET_MPS_CTRL_ADDR;
	memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
	msg_to_mpoad(&mesg, mpc);
}
示例#7
0
/*
 * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
 */
static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
{

	eg_cache_entry *entry;
	msg->type = SND_EGRESS_PURGE;


	/* FIXME: This knows too much of the cache structure */
	read_lock_irq(&mpc->egress_lock);
	entry = mpc->eg_cache;
	while (entry != NULL) {
		msg->content.eg_info = entry->ctrl_info;
		dprintk("cache_id %u\n", entry->ctrl_info.cache_id);
		msg_to_mpoad(msg, mpc);
		entry = entry->next;
	}
	read_unlock_irq(&mpc->egress_lock);

	msg->type = action;
	msg_to_mpoad(msg, mpc);
}
示例#8
0
/* 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);
}