Ejemplo n.º 1
0
int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	struct dn_scp *scp = DN_SK(sk);
	struct sk_buff *skb2, *n, *ack = NULL;
	int wakeup = 0;
	int try_retrans = 0;
	unsigned long reftime = cb->stamp;
	unsigned long pkttime;
	unsigned short xmit_count;
	unsigned short segnum;

	skb_queue_walk_safe(q, skb2, n) {
		struct dn_skb_cb *cb2 = DN_SKB_CB(skb2);

		if (dn_before_or_equal(cb2->segnum, acknum))
			ack = skb2;

		

		if (ack == NULL)
			continue;

		

		
		try_retrans = 0;
		
		wakeup = 1;
		
		pkttime = cb2->stamp;
		xmit_count = cb2->xmit_count;
		segnum = cb2->segnum;
		
		skb_unlink(ack, q);
		kfree_skb(ack);
		ack = NULL;

		
		WARN_ON(xmit_count == 0);

		
		if (xmit_count == 1) {
			if (dn_equal(segnum, acknum))
				dn_nsp_rtt(sk, (long)(pkttime - reftime));

			if (scp->snd_window < scp->max_window)
				scp->snd_window++;
		}

		
		if (xmit_count > 1)
			try_retrans = 1;
	}

	if (try_retrans)
		dn_nsp_output(sk);

	return wakeup;
}
Ejemplo n.º 2
0
int dn_nsp_xmit_timeout(struct sock *sk)
{
	struct dn_scp *scp = DN_SK(sk);

	dn_nsp_output(sk);

	if (!skb_queue_empty(&scp->data_xmit_queue) ||
	    !skb_queue_empty(&scp->other_xmit_queue))
		scp->persist = dn_nsp_persist(sk);

	return 0;
}
Ejemplo n.º 3
0
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
{
	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
	unsigned short segnum;
	unsigned char lsflags;
	char fcval;

	if (skb->len != 4)
		goto out;

	cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data);
	skb_pull(skb, 2);
	lsflags = *(unsigned char *)skb->data;
	skb_pull(skb, 1);
	fcval = *(char *)skb->data;

	if (lsflags & 0xf0)
		goto out;

	if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0FFF) == (segnum & 0x0FFF)) {
        	sk->protinfo.dn.numoth_rcv += 1;        
                switch(lsflags & 0x03) {
                	case 0x00:      
                        	break;
                        case 0x01:      
                                sk->protinfo.dn.flowrem_sw = DN_DONTSEND;
                                break;
                        case 0x02:      
                                sk->protinfo.dn.flowrem_sw = DN_SEND;
				dn_nsp_output(sk);
				if (!sk->dead)
					sk->state_change(sk);
                }
                
        }

	dn_nsp_send_oth_ack(sk);

out:
	kfree_skb(skb);
}
Ejemplo n.º 4
0
int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	struct dn_scp *scp = DN_SK(sk);
	struct sk_buff *skb2, *n, *ack = NULL;
	int wakeup = 0;
	int try_retrans = 0;
	unsigned long reftime = cb->stamp;
	unsigned long pkttime;
	unsigned short xmit_count;
	unsigned short segnum;

	skb_queue_walk_safe(q, skb2, n) {
		struct dn_skb_cb *cb2 = DN_SKB_CB(skb2);

		if (dn_before_or_equal(cb2->segnum, acknum))
			ack = skb2;

		/* printk(KERN_DEBUG "ack: %s %04x %04x\n", ack ? "ACK" : "SKIP", (int)cb2->segnum, (int)acknum); */

		if (ack == NULL)
			continue;

		/* printk(KERN_DEBUG "check_xmit_queue: %04x, %d\n", acknum, cb2->xmit_count); */

		/* Does _last_ packet acked have xmit_count > 1 */
		try_retrans = 0;
		/* Remember to wake up the sending process */
		wakeup = 1;
		/* Keep various statistics */
		pkttime = cb2->stamp;
		xmit_count = cb2->xmit_count;
		segnum = cb2->segnum;
		/* Remove and drop ack'ed packet */
		skb_unlink(ack, q);
		kfree_skb(ack);
		ack = NULL;

		/*
		 * We don't expect to see acknowledgements for packets we
		 * haven't sent yet.
		 */
		WARN_ON(xmit_count == 0);

		/*
		 * If the packet has only been sent once, we can use it
		 * to calculate the RTT and also open the window a little
		 * further.
		 */
		if (xmit_count == 1) {
			if (dn_equal(segnum, acknum))
				dn_nsp_rtt(sk, (long)(pkttime - reftime));

			if (scp->snd_window < scp->max_window)
				scp->snd_window++;
		}

		/*
		 * Packet has been sent more than once. If this is the last
		 * packet to be acknowledged then we want to send the next
		 * packet in the send queue again (assumes the remote host does
		 * go-back-N error control).
		 */
		if (xmit_count > 1)
			try_retrans = 1;
	}

	if (try_retrans)
		dn_nsp_output(sk);

	return wakeup;
}
Ejemplo n.º 5
0
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
{
	struct dn_scp *scp = DN_SK(sk);
	unsigned short segnum;
	unsigned char lsflags;
	signed char fcval;
	int wake_up = 0;
	char *ptr = skb->data;
	unsigned char fctype = scp->services_rem & NSP_FC_MASK;

	if (skb->len != 4)
		goto out;

	segnum = le16_to_cpu(*(__le16 *)ptr);
	ptr += 2;
	lsflags = *(unsigned char *)ptr++;
	fcval = *ptr;

	/*
	 * Here we ignore erronous packets which should really
	 * should cause a connection abort. It is not critical
	 * for now though.
	 */
	if (lsflags & 0xf8)
		goto out;

	if (seq_next(scp->numoth_rcv, segnum)) {
		seq_add(&scp->numoth_rcv, 1);
		switch(lsflags & 0x04) { /* FCVAL INT */
		case 0x00: /* Normal Request */
			switch(lsflags & 0x03) { /* FCVAL MOD */
			case 0x00: /* Request count */
				if (fcval < 0) {
					unsigned char p_fcval = -fcval;
					if ((scp->flowrem_dat > p_fcval) &&
					    (fctype == NSP_FC_SCMC)) {
						scp->flowrem_dat -= p_fcval;
					}
				} else if (fcval > 0) {
					scp->flowrem_dat += fcval;
					wake_up = 1;
				}
				break;
			case 0x01: /* Stop outgoing data */
				scp->flowrem_sw = DN_DONTSEND;
				break;
			case 0x02: /* Ok to start again */
				scp->flowrem_sw = DN_SEND;
				dn_nsp_output(sk);
				wake_up = 1;
			}
			break;
		case 0x04: /* Interrupt Request */
			if (fcval > 0) {
				scp->flowrem_oth += fcval;
				wake_up = 1;
			}
			break;
		}
		if (wake_up && !sock_flag(sk, SOCK_DEAD))
			sk->sk_state_change(sk);
	}

	dn_nsp_send_oth_ack(sk);

out:
	kfree_skb(skb);
}
Ejemplo n.º 6
0
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
{
	struct dn_scp *scp = DN_SK(sk);
	unsigned short segnum;
	unsigned char lsflags;
	signed char fcval;
	int wake_up = 0;
	char *ptr = skb->data;
	unsigned char fctype = scp->services_rem & NSP_FC_MASK;

	if (skb->len != 4)
		goto out;

	segnum = le16_to_cpu(*(__le16 *)ptr);
	ptr += 2;
	lsflags = *(unsigned char *)ptr++;
	fcval = *ptr;

	
	if (lsflags & 0xf8)
		goto out;

	if (seq_next(scp->numoth_rcv, segnum)) {
		seq_add(&scp->numoth_rcv, 1);
		switch(lsflags & 0x04) { 
		case 0x00: 
			switch(lsflags & 0x03) { 
			case 0x00: 
				if (fcval < 0) {
					unsigned char p_fcval = -fcval;
					if ((scp->flowrem_dat > p_fcval) &&
					    (fctype == NSP_FC_SCMC)) {
						scp->flowrem_dat -= p_fcval;
					}
				} else if (fcval > 0) {
					scp->flowrem_dat += fcval;
					wake_up = 1;
				}
				break;
			case 0x01: 
				scp->flowrem_sw = DN_DONTSEND;
				break;
			case 0x02: 
				scp->flowrem_sw = DN_SEND;
				dn_nsp_output(sk);
				wake_up = 1;
			}
			break;
		case 0x04: 
			if (fcval > 0) {
				scp->flowrem_oth += fcval;
				wake_up = 1;
			}
			break;
		}
		if (wake_up && !sock_flag(sk, SOCK_DEAD))
			sk->sk_state_change(sk);
	}

	dn_nsp_send_oth_ack(sk);

out:
	kfree_skb(skb);
}