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

📄 snoop.c

📁 一种无线拥塞控制协议
💻 C
📖 第 1 页 / 共 3 页
字号:
			spin_lock_irqsave(&retransmit_packet->lock, retransmit_packet->irqflags);		if (retransmit_packet->num_rxmit < SNOOP_MAX_RXMIT && retransmit_packet->skb != 0){		snoop_forward (retransmit_packet->skb, retransmit_packet);				if (SNOOP_DEBUG) printk("..adding timer..");		retransmit_packet->num_rxmit++;		retransmit_packet->departure = jiffies;		init_timer(&retransmit_packet->rexmit);		retransmit_packet->rexmit.expires = jiffies + 2 * cs->rto;		retransmit_packet->rexmit.function = &snoop_packet_retransmit;		retransmit_packet->rexmit.data = (unsigned long) retransmit_packet;		add_timer(&retransmit_packet->rexmit);	}	spin_unlock_irqrestore(&retransmit_packet->lock, retransmit_packet->irqflags);		if (SNOOP_DEBUG) printk("..DONE.\n\n");}//============ SNOOP FORWARD - forward packet given packet pointer =========/* * This function uses the kernel symbol snoop_ip_forward_finish() to push * the buffered sk_buff into the IP stacks, so that it can be forwarded by * the kernel.  Before forwarding, the buffer must be unlinked from the  * sk_buff linked list maintained by the kernel.  Since the buffer is  * freed, after a packet is sent out on the medium, not unlinking it from * the kernel might cause the kernel to go into panic. */int snoop_forward (struct sk_buff * skb, snoop_packet_t * forward_packet){	struct sk_buff * forward;	if (skb != 0){	       	if(snoop_ip_forward_finish && (forward = snoop_skb_clone(skb))){			skb_unlink(forward);		       	(* snoop_ip_forward_finish) (forward);		}	if (SNOOP_DEBUG) printk ("done forwarding.\n");	}	return SNOOPE_SUCCESS;}//============ SNOOP SAVE PACEKT - fills in the packet structure ===========/* * The snoop_save_packet(.) function receives the pointer to the packet  * container (snoop_packet), the id of the connection, under which to add * the packet, and the snoop buffer, which contains the buffer and the  * other information required to make the snoop buffer.  If the packet is * a duplicate packet which already resides in the buffer, then the size of * the payload ofthe new packet is checked against the one in the buffer.  * If the new packet contains more data than the previous, the older one is * replaced by the newer one.   * * The spinlock is set down before the operation on the snoop_packet * begins.  The buffer is copied using snoop_skb_copy, and the variables * int the snoop packet are set using the values in the snoop buffer. * * The timer is set using the RTO value from the connection state struct. * The spinlock is unlocked, and the function returns. */int snoop_save_packet (snoop_packet_t * save_packet, struct snoop_buffer * snb, unsigned int conn_id){	snoop_cs_t *cs = snoop_control.cstate[conn_id];	if (SNOOP_DEBUG) printk("buffering pack with seq # %u ...", snb->seq);	if (save_packet->seq == snb->seq){		if (SNOOP_DEBUG) printk ("duplicate BUFF[%u][%u] PKT[%u][%u]...REPLACING", snb->seq, snb->size, save_packet->seq, save_packet->size);		 snoop_free_packet (save_packet);	}			spin_lock_irqsave(&save_packet->lock, save_packet->irqflags);		save_packet->skb = snoop_skb_clone(snb->skb);	save_packet->conn_id = conn_id;	save_packet->seq = snb->seq;	save_packet->size = snb->size;	save_packet->departure = jiffies;	save_packet->num_rxmit = 0;//	save_packet->sock = snb->sock;	init_timer(&save_packet->rexmit);	save_packet->rexmit.expires = jiffies + 2 * cs->rto;	save_packet->rexmit.data = (unsigned long)save_packet;	save_packet->rexmit.function = &snoop_packet_retransmit;	add_timer(&save_packet->rexmit);	spin_unlock_irqrestore(&save_packet->lock, save_packet->irqflags);	if (SNOOP_DEBUG) printk("done");	return SNOOPE_SUCCESS;}//============ SNOOP RTO CALC - estimates the rto over one hop =============/* * The fucntion is passed the pointer to the connection, the RTO of which  * nees to be updated, and the time of departure of the last packet which * has just been acknowledged. * * The function calculates the RTT, and using hte formula below, it  * computes the RTO, and updates the value in the connection state. */void snoop_rto_calc (snoop_cs_t * cs, unsigned long last){	if (cs->state & SNOOP_NOACK){	       	cs->rto = jiffies - last;	       	cs->state &= ~SNOOP_NOACK;		if (SNOOP_DEBUG) printk("- FIRST-: [%lu] ",cs->rto);	}	else		cs->rto = (0.75*cs->rto) + (0.25 * (jiffies - last));	if (SNOOP_DEBUG) printk("-Jiff:[%lu] | last:[%lu] | RTO:[%lu]- ", jiffies, last, cs->rto);	return;}//============ SNOOP ACK - handles ack packets from MH =====================/* * To determine what action to take with the newly received packet form  * the Mobile Host, a series of checks are performed.  If the packet does * not have the acknowledgement bit set, the function returns, and no  * operation is performed on using the packet.   *  * If the acknowledgement sequence number is equal to the last received  * acknowledgement, then local recovery is performed for the requested  * packet.  The packet which is being demanded by the mobile host will  * be transmitted using the snoop_forward(.) function, only if the  * maximum number of retransmissions has not been exceeded.  The dupack * is dropped, so that it does not traverse to the Fixed host.  In case * the maximum number of retransmissions has been reached, no action is * taken and the duplicate ack is propagated to the fixed host. * * If the acknowledgement sequence number is greater than the last received  * acknowledgement, the acknowledgement is new, and it is used to empty the  * packet buffer for that connection.  snoop_clean_buff(.) is invoked to  * clean the buffer using the acknowledgement sequence number. */int snoop_ack(struct snoop_buffer *snb, unsigned int conn_id){	snoop_cs_t *cs = snoop_control.cstate[conn_id];	snoop_packet_t * head_packet;		int toReturn = SNOOPE_SUCCESS;	if (SNOOP_DEBUG) printk("SNOOP: ==Mobile Host== [");	if (!snb->flags->ack || snb->ack_seq < cs->last_ack) { // if ack bit is not even set		if (SNOOP_DEBUG) printk(" Old Acknowledgement - allow it to pass through ]\n");		toReturn = SNOOPE_SUCCESS;		goto final;	}	if (snb->ack_seq == cs->last_ack){ // Duplicate Ack		if (SNOOP_DEBUG) printk("last_ack[%u] this ack[%u]", cs->last_ack, snb->ack_seq);		head_packet = cs->pkts[NEXT(cs->head)];		if (SNOOP_DEBUG) printk("-duplicate ack-");		if (cs->state & SNOOP_DUPACK){			cs->state &= ~SNOOP_DUPACK;			if (head_packet->num_rxmit <= SNOOP_MAX_RXMIT){				if (SNOOP_DEBUG) printk("RETRANSMITTING.");				toReturn = SNOOPE_DROP;				snoop_forward (head_packet->skb, head_packet);				++head_packet->num_rxmit;			}			else {				if (SNOOP_DEBUG) printk("FORWARDING.");			}						goto final;		}else{		       	cs->state |= SNOOP_DUPACK;			toReturn = SNOOPE_SUCCESS;		}	}	if (snb->ack_seq > cs->last_ack){ // if it is a pure ack		if (SNOOP_DEBUG) printk("-pure ack-");		cs->last_ack = snb->ack_seq;		snoop_clean_buff(conn_id, snb->ack_seq);	}final:	kfree(snb->sock);	kfree(snb->flags);	kfree(snb);	if (SNOOP_DEBUG) printk(" ]\n\n");	return toReturn;}//============ SNOOP CLEANBUF - remove acked packets =======================/* * This function clears all the packets from the buffer with the sequence  * numbers less than the acknowledgement sequence number.  If the buffer  * is empty, the function simply returns without performing any action.   * * The packets are cleared using the snoop_clean_packet() function. * If there are packets to clean, then the packet to which the  * acknowledgement belongs is isolated.  The departure is temporarily * stored so that when all the packets that could be cleared are free, * the snoop_rto_calc function is called to update the RTO for the  * connection.  * * If buffer is cleared, the snoop buffer full status us unset, so * that packts could be cached again from then on. */void snoop_clean_buff (unsigned int conn_id, unsigned int ack_seq){	snoop_cs_t *cs = snoop_control.cstate[conn_id];	int i;	char flag = 0;	snoop_packet_t *clean_packet;	unsigned long last = 1;	if (SNOOP_DEBUG) printk(" cleaning packetets acked by ack_seq %u... (", ack_seq);	// If packet buffer is empty, then just return.	if (NEXT(cs->head) == cs->tail && !(cs->state & SNOOP_FULL)){		if (SNOOP_DEBUG) printk(" no packets to clean ) ...done.");		return;	}	// Empty all packets that have been acked	i = cs->head;	flag = 0;	for (i = NEXT(cs->head); NEXT(i) != cs->head || !flag; i = NEXT(i)){		clean_packet = cs->pkts[i];		if (ack_seq < clean_packet->seq || clean_packet->seq == 0) {break;break;}		last = clean_packet->departure;		if (SNOOP_DEBUG) printk("- Dep: [%lu] ",last);		snoop_free_packet(clean_packet);		flag = 1;	}	// Set head to the oldest packet not acked	if (flag) {		snoop_rto_calc(cs, last);		cs->state &= ~SNOOP_FULL;		cs->head = PREV(i);		if (cs->state & SNOOP_FULL) printk("**** FULL ***");		if (SNOOP_DEBUG) printk(" -head [%2d] tail [%2d]- ", cs->head, cs->tail);	}		if (SNOOP_DEBUG) printk(") done");	return;}//============ SNOOP FREE PACKET - empties the contents of a packet=========/* * Before the packet is operated on, the spinlock for the packet is set * down to avoid race conditions.  The snoop_free_packet(.) function calls  * the snoop_free_skb(.) to free the memory for the cloned sk_buff that it  * had stored within it. The timers are cleared, and the variables are  * initialized to zero. */void snoop_free_packet (snoop_packet_t *free_packet){	if (SNOOP_DEBUG) printk(" freeing pkt with seq: %u...", free_packet->seq);	spin_lock_irqsave(&free_packet->lock, free_packet->irqflags);	if (SNOOP_DEBUG) printk("=lock=");	if (SNOOP_DEBUG) printk("=deltiemr=");		if (free_packet->skb){		snoop_free_skb(free_packet->skb); // Clear skb if it exists		free_packet->skb = 0;		del_timer(&free_packet->rexmit);	}		//	if (free_packet->sock)kfree (free_packet->sock);		free_packet->conn_id = 0;	free_packet->seq = 0;	free_packet->size = 0;	free_packet->num_rxmit = 0;	free_packet->skb = 0;	free_packet->sock = 0;	spin_unlock_irqrestore(&free_packet->lock, free_packet->irqflags);		if (SNOOP_DEBUG) printk("...done.");	return;}//============ SNOOP FREE SKB - empties the skb from packet ================/* * The  snoop_free_skb(.) function takes in a pointer to the sk_buff.  If  * the sk_buff exists, its occupied memory is freed.  If the pointer is  * null, the function simply returns. */void snoop_free_skb (struct sk_buff * free_skb){	if (free_skb){		kfree_skb(free_skb); // Clear skb if it exists		return;	}	return;}//============ SNOOP CLEAN CONN - cleans connection state===================/* * The clean_conn function clears the snoop connection state once a  * connction which was being handled by the snoop module terminates.  This * can happen either when the connection times out, or a fin flag is read * from the packets belonging to this connection. * * All the packets belonging to that conection are cleaned, and the timer * is unset. The connection structure variables are all initialized to  * zero, and the number of free connections is incremented. */void snoop_clean_conn(unsigned int conn_id){	snoop_cs_t *cs = snoop_control.cstate[conn_id];	int i;	if (SNOOP_DEBUG) printk("SNOOP: Cleaning up connection [%3d]... ", conn_id);	down (&cs->mutex);	del_timer(&cs->timeout);	cs->state = SNOOP_CLOSED;	snoop_control.num_connections--;	cs->last_seq = cs->last_ack = 0;	cs->rto = SNOOP_RTO;	// Free all packets.	for (i = 0; i < SNOOP_MAXWINDOW; i++){		if (SNOOP_DEBUG) printk("\nSNOOP: packet [%3d] =", i);		snoop_free_packet(cs->pkts[i]);	}	cs->head = 0;

⌨️ 快捷键说明

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