⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		stop_mpc(mpc);		mpc->dev = NULL;		break;	case NETDEV_UP:		/* the dev was ifconfig'ed up */		mpc = find_mpc_by_lec(dev);		if (mpc == NULL)			break;		if (mpc->mpoad_vcc != NULL) {			start_mpc(mpc, dev);		}		break;	case NETDEV_DOWN:		/* the dev was ifconfig'ed down */		/* this means that the flow of packets from the		 * upper layer stops		 */		mpc = find_mpc_by_lec(dev);		if (mpc == NULL)			break;		if (mpc->mpoad_vcc != NULL) {			stop_mpc(mpc);		}		break;	case NETDEV_REBOOT:	case NETDEV_CHANGE:	case NETDEV_CHANGEMTU:	case NETDEV_CHANGEADDR:	case NETDEV_GOING_DOWN:		break;	default:		break;	}	return NOTIFY_DONE;}/* * Functions which are called after a message is received from mpcd. * Msg is reused on purpose. */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;}/* * 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 __attribute__ ((unused)) = (unsigned char *)&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(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 void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc){	unsigned char *ip;	uint32_t dst_ip = msg->content.in_info.in_dst_ip;	in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);	ip = (unsigned char *)&dst_ip;	dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));	ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);	if(entry == NULL){		printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);		return;	}	ddprintk(" entry_state = %d ", entry->entry_state);		if (entry->entry_state == INGRESS_RESOLVED) {		printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);		mpc->in_ops->put(entry);		return;	}	entry->ctrl_info = msg->content.in_info;	do_gettimeofday(&(entry->tv));	do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */	entry->refresh_time = 0;	ddprintk("entry->shortcut = %p\n", entry->shortcut);	if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){		entry->entry_state = INGRESS_RESOLVED; 		mpc->in_ops->put(entry);		return; /* Shortcut already open... */	}	if (entry->shortcut != NULL) {		printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",		       mpc->dev->name);		mpc->in_ops->put(entry);		return;	}		check_qos_and_open_shortcut(msg, mpc, entry);	entry->entry_state = INGRESS_RESOLVED;	mpc->in_ops->put(entry);	return;}static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc){	uint32_t dst_ip = msg->content.in_info.in_dst_ip;	uint32_t mask = msg->ip_mask;	unsigned char *ip = (unsigned char *)&dst_ip;	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);	if(entry == NULL){		printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);		printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);		return;	}	do {		dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,			mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);		write_lock_bh(&mpc->ingress_lock);		mpc->in_ops->remove_entry(entry, mpc);		write_unlock_bh(&mpc->ingress_lock);		mpc->in_ops->put(entry);		entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);	} while (entry != NULL);	return;} static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc){	uint32_t cache_id = msg->content.eg_info.cache_id;	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);		if (entry == NULL) {		dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);		return;	}	write_lock_irq(&mpc->egress_lock);	mpc->eg_ops->remove_entry(entry, mpc);	write_unlock_irq(&mpc->egress_lock);	mpc->eg_ops->put(entry);	return;} static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry){	struct k_message *purge_msg;	struct sk_buff *skb;	dprintk("mpoa: purge_egress_shortcut: entering\n");	if (vcc == NULL) {		printk("mpoa: purge_egress_shortcut: vcc == NULL\n");		return;	}	skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);	if (skb == NULL) {		 printk("mpoa: purge_egress_shortcut: out of memory\n");		return;	}	skb_put(skb, sizeof(struct k_message));	memset(skb->data, 0, sizeof(struct k_message));	purge_msg = (struct k_message *)skb->data;	purge_msg->type = DATA_PLANE_PURGE;	if (entry != NULL)		purge_msg->content.eg_info = entry->ctrl_info;	atm_force_charge(vcc, skb->truesize);	skb_queue_tail(&vcc->recvq, skb);	wake_up(&vcc->sleep);	dprintk("mpoa: purge_egress_shortcut: exiting:\n");	return;}/* * Our MPS died. Tell our daemon to send NHRP data plane purge to each * of the egress shortcuts we have. */static void mps_death( struct k_message * msg, struct mpoa_client * mpc ){	eg_cache_entry *entry;	dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);	if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){		printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);		return;	}	/* FIXME: This knows too much of the cache structure */	read_lock_irq(&mpc->egress_lock);	entry = mpc->eg_cache;	while (entry != NULL) {		purge_egress_shortcut(entry->shortcut, entry);		entry = entry->next;	}	read_unlock_irq(&mpc->egress_lock);	mpc->in_ops->destroy_cache(mpc);	mpc->eg_ops->destroy_cache(mpc);	return;}static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc){	uint16_t holding_time;	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);		holding_time = msg->content.eg_info.holding_time;	dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",	       mpc->dev->name, entry, holding_time);	if(entry == NULL && holding_time) {		entry = mpc->eg_ops->add_entry(msg, mpc);		mpc->eg_ops->put(entry);		return;	}	if(holding_time){		mpc->eg_ops->update(entry, holding_time);		return;	}		write_lock_irq(&mpc->egress_lock);	mpc->eg_ops->remove_entry(entry, mpc);	write_unlock_irq(&mpc->egress_lock);	mpc->eg_ops->put(entry);		return;}static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc){	struct lec_priv *priv;	int i, retval ;	uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];	tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type  */	tlv[4] = 1 + 1 + ATM_ESA_LEN;  /* length                           */	tlv[5] = 0x02;                 /* MPOA client                      */	tlv[6] = 0x00;                 /* number of MPS MAC addresses      */	memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */	memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);	dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",	       (mpc->dev) ? mpc->dev->name : "<unknown>");	for (i = 7; i < sizeof(tlv); i++)		dprintk("%02x ", tlv[i]);	dprintk("\n");	if (mpc->dev) {		priv = (struct lec_priv *)mpc->dev->priv;		retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));		if (retval == 0)			printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);		retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);		if (retval < 0)			printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);	}	return;}static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client){	if(client->number_of_mps_macs)		kfree(client->mps_macs);	client->number_of_mps_macs = 0;	client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);	if (client->mps_macs == NULL) {		printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");		return;	}	client->number_of_mps_macs = 1;	memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);		return;}/* * 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("mpoa: 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);	return;}static void mpc_timer_refresh(){	mpc_timer.expires = jiffies + (MPC_P2 * HZ);	mpc_timer.data = mpc_timer.expires;	mpc_timer.function = mpc_cache_check;	add_timer(&mpc_timer);		return;}static void mpc_cache_check( unsigned long checking_time  ){	struct mpoa_client *mpc = mpcs;	static unsigned long previous_resolving_check_time = 0;	static unsigned long previous_refresh_time = 0;		while( mpc != NULL ){		mpc->in_ops->clear_count(mpc);		mpc->eg_ops->clear_expired(mpc);		if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){			mpc->in_ops->check_resolving(mpc);			previous_resolving_check_time = checking_time;		}		if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){			mpc->in_ops->refresh(mpc);			previous_refresh_time = checking_time;		}		mpc = mpc->next;	}	mpc_timer_refresh();		return;}void atm_mpoa_init_ops(struct atm_mpoa_ops *ops){	ops->mpoad_attach = atm_mpoa_mpoad_attach;	ops->vcc_attach = atm_mpoa_vcc_attach;#ifdef CONFIG_PROC_FS	if(mpc_proc_init() != 0)		printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");	else		printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");#endif	printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");	return;}#ifdef MODULEint init_module(void){	extern struct atm_mpoa_ops atm_mpoa_ops;	atm_mpoa_init_ops(&atm_mpoa_ops);	return 0;}void cleanup_module(void){	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) {		printk("mpc.c: module in use\n");		return;	}#ifdef CONFIG_PROC_FS	mpc_proc_clean();#endif	del_timer(&mpc_timer);	unregister_netdevice_notifier(&mpoa_notifier);	atm_mpoa_ops.mpoad_attach = NULL;	atm_mpoa_ops.vcc_attach = NULL;	mpc = mpcs;	mpcs = NULL;	while (mpc != NULL) {		tmp = mpc->next;		if (mpc->dev != NULL) {			stop_mpc(mpc);			priv = (struct lec_priv *)mpc->dev->priv;			if (priv->lane2_ops != NULL)				priv->lane2_ops->associate_indicator = NULL;		}		ddprintk("mpoa: cleanup_module: about to clear caches\n");		mpc->in_ops->destroy_cache(mpc);		mpc->eg_ops->destroy_cache(mpc);		ddprintk("mpoa: cleanup_module: caches cleared\n");		kfree(mpc->mps_macs);		memset(mpc, 0, sizeof(struct mpoa_client));		ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);		kfree(mpc);		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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -