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; }
static __le16 *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) { struct dn_scp *scp = DN_SK(sk); unsigned short acknum = scp->numdat_rcv & 0x0FFF; unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; __le16 *ptr; BUG_ON(hlen < 9); scp->ackxmt_dat = acknum; scp->ackxmt_oth = ackcrs; acknum |= 0x8000; ackcrs |= 0x8000; if (other) { unsigned short tmp = acknum; acknum = ackcrs; ackcrs = tmp; } ackcrs |= 0x2000; ptr = (__le16 *)dn_mk_common_header(scp, skb, msgflag, hlen); *ptr++ = cpu_to_le16(acknum); *ptr++ = cpu_to_le16(ackcrs); return ptr; }
static void dn_nsp_send(struct sk_buff *skb) { struct sock *sk = skb->sk; struct dn_scp *scp = DN_SK(sk); struct dst_entry *dst; struct flowi fl; skb_reset_transport_header(skb); scp->stamp = jiffies; dst = sk_dst_check(sk, 0); if (dst) { try_again: skb_dst_set(skb, dst); dst_output(skb); return; } memset(&fl, 0, sizeof(fl)); fl.oif = sk->sk_bound_dev_if; fl.fld_src = dn_saddr2dn(&scp->addr); fl.fld_dst = dn_saddr2dn(&scp->peer); dn_sk_ports_copy(&fl, scp); fl.proto = DNPROTO_NSP; if (dn_route_output_sock(&sk->sk_dst_cache, &fl, sk, 0) == 0) { dst = sk_dst_get(sk); sk->sk_route_caps = dst->dev->features; goto try_again; } sk->sk_err = EHOSTUNREACH; if (!sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); }
static void dn_nsp_rtt(struct sock *sk, long rtt) { struct dn_scp *scp = DN_SK(sk); long srtt = (long)scp->nsp_srtt; long rttvar = (long)scp->nsp_rttvar; long delta; if (rtt < 0) rtt = -rtt; delta = ((rtt << 3) - srtt); srtt += (delta >> 3); if (srtt >= 1) scp->nsp_srtt = (unsigned long)srtt; else scp->nsp_srtt = 1; delta >>= 1; rttvar += ((((delta>0)?(delta):(-delta)) - rttvar) >> 2); if (rttvar >= 1) scp->nsp_rttvar = (unsigned long)rttvar; else scp->nsp_rttvar = 1; }
void dn_nsp_output(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; unsigned reduce_win = 0; if ((skb = skb_peek(&scp->other_xmit_queue)) != NULL) reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); if (reduce_win || (scp->flowrem_sw != DN_SEND)) goto recalc_window; if ((skb = skb_peek(&scp->data_xmit_queue)) != NULL) reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); recalc_window: if (reduce_win) { scp->snd_window >>= 1; if (scp->snd_window < NSP_MIN_WINDOW) scp->snd_window = NSP_MIN_WINDOW; } }
static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); unsigned short segnum; struct dn_skb_cb *cb = DN_SKB_CB(skb); int queued = 0; if (skb->len < 2) goto out; cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numoth_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) { seq_add(&scp->numoth_rcv, 1); scp->other_report = 0; queued = 1; } } dn_nsp_send_oth_ack(sk); out: if (!queued) kfree_skb(skb); }
static void dn_nsp_data(struct sock *sk, struct sk_buff *skb) { int queued = 0; unsigned short segnum; struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dn_scp *scp = DN_SK(sk); if (skb->len < 2) goto out; cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numdat_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) { seq_add(&scp->numdat_rcv, 1); queued = 1; } if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) { scp->flowloc_sw = DN_DONTSEND; dn_nsp_send_link(sk, DN_DONTSEND, 0); } } dn_nsp_send_data_ack(sk); out: if (!queued) kfree_skb(skb); }
void dn_nsp_output(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; unsigned reduce_win = 0; /* * First we check for otherdata/linkservice messages */ if ((skb = skb_peek(&scp->other_xmit_queue)) != NULL) reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); /* * If we may not send any data, we don't. * If we are still trying to get some other data down the * channel, we don't try and send any data. */ if (reduce_win || (scp->flowrem_sw != DN_SEND)) goto recalc_window; if ((skb = skb_peek(&scp->data_xmit_queue)) != NULL) reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); /* * If we've sent any frame more than once, we cut the * send window size in half. There is always a minimum * window size of one available. */ recalc_window: if (reduce_win) { scp->snd_window >>= 1; if (scp->snd_window < NSP_MIN_WINDOW) scp->snd_window = NSP_MIN_WINDOW; } }
static __le16 *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) { struct dn_scp *scp = DN_SK(sk); unsigned short acknum = scp->numdat_rcv & 0x0FFF; unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; __le16 *ptr; BUG_ON(hlen < 9); scp->ackxmt_dat = acknum; scp->ackxmt_oth = ackcrs; acknum |= 0x8000; ackcrs |= 0x8000; /* If this is an "other data/ack" message, swap acknum and ackcrs */ if (other) { unsigned short tmp = acknum; acknum = ackcrs; ackcrs = tmp; } /* Set "cross subchannel" bit in ackcrs */ ackcrs |= 0x2000; ptr = (__le16 *)dn_mk_common_header(scp, skb, msgflag, hlen); *ptr++ = cpu_to_le16(acknum); *ptr++ = cpu_to_le16(ackcrs); return ptr; }
void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; cb->xmit_count = 0; dn_nsp_mk_data_header(sk, skb, oth); /* * Slow start: If we have been idle for more than * one RTT, then reset window to min size. */ if ((jiffies - scp->stamp) > t) scp->snd_window = NSP_MIN_WINDOW; if (oth) skb_queue_tail(&scp->other_xmit_queue, skb); else skb_queue_tail(&scp->data_xmit_queue, skb); if (scp->flowrem_sw != DN_SEND) return; dn_nsp_clone_and_send(skb, gfp); }
void dn_send_conn_conf(struct sock *sk, gfp_t gfp) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_init_msg *msg; __u8 len = (__u8)le16_to_cpu(scp->conndata_out.opt_optl); if ((skb = dn_alloc_skb(sk, 50 + len, gfp)) == NULL) return; msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg)); msg->msgflg = 0x28; msg->dstaddr = scp->addrrem; msg->srcaddr = scp->addrloc; msg->services = scp->services_loc; msg->info = scp->info_loc; msg->segsize = cpu_to_le16(scp->segsize_loc); *skb_put(skb,1) = len; if (len > 0) memcpy(skb_put(skb, len), scp->conndata_out.opt_data, len); dn_nsp_send(skb); scp->persist = dn_nsp_persist(sk); scp->persist_fxn = dn_nsp_retrans_conn_conf; }
static void dn_slow_timer(unsigned long arg) { struct sock *sk = (struct sock *)arg; struct dn_scp *scp = DN_SK(sk); bh_lock_sock(sk); if (sock_owned_by_user(sk)) { sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 10); goto out; } if (scp->persist && scp->persist_fxn) { if (scp->persist <= SLOW_INTERVAL) { scp->persist = 0; if (scp->persist_fxn(sk)) goto out; } else { scp->persist -= SLOW_INTERVAL; } } if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) { if ((jiffies - scp->stamp) >= scp->keepalive) scp->keepalive_fxn(sk); } sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL); out: bh_unlock_sock(sk); sock_put(sk); }
/* * For this function we've flipped the cross-subchannel bit * if the message is an otherdata or linkservice message. Thus * we can use it to work out what to update. */ static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack) { struct dn_scp *scp = DN_SK(sk); unsigned short type = ((ack >> 12) & 0x0003); int wakeup = 0; switch (type) { case 0: /* ACK - Data */ if (dn_after(ack, scp->ackrcv_dat)) { scp->ackrcv_dat = ack & 0x0fff; wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->data_xmit_queue, ack); } break; case 1: /* NAK - Data */ break; case 2: /* ACK - OtherData */ if (dn_after(ack, scp->ackrcv_oth)) { scp->ackrcv_oth = ack & 0x0fff; wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->other_xmit_queue, ack); } break; case 3: /* NAK - OtherData */ break; } if (wakeup && !sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); }
static void dn_slow_timer(unsigned long arg) { struct sock *sk = (struct sock *)arg; struct dn_scp *scp = DN_SK(sk); sock_hold(sk); bh_lock_sock(sk); if (sock_owned_by_user(sk)) { sk->sk_timer.expires = jiffies + HZ / 10; add_timer(&sk->sk_timer); goto out; } /* * The persist timer is the standard slow timer used for retransmits * in both connection establishment and disconnection as well as * in the RUN state. The different states are catered for by changing * the function pointer in the socket. Setting the timer to a value * of zero turns it off. We allow the persist_fxn to turn the * timer off in a permant way by returning non-zero, so that * timer based routines may remove sockets. This is why we have a * sock_hold()/sock_put() around the timer to prevent the socket * going away in the middle. */ if (scp->persist && scp->persist_fxn) { if (scp->persist <= SLOW_INTERVAL) { scp->persist = 0; if (scp->persist_fxn(sk)) goto out; } else { scp->persist -= SLOW_INTERVAL; } } /* * Check for keepalive timeout. After the other timer 'cos if * the previous timer caused a retransmit, we don't need to * do this. scp->stamp is the last time that we sent a packet. * The keepalive function sends a link service packet to the * other end. If it remains unacknowledged, the standard * socket timers will eventually shut the socket down. Each * time we do this, scp->stamp will be updated, thus * we won't try and send another until scp->keepalive has passed * since the last successful transmission. */ if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) { if ((jiffies - scp->stamp) >= scp->keepalive) scp->keepalive_fxn(sk); } sk->sk_timer.expires = jiffies + SLOW_INTERVAL; add_timer(&sk->sk_timer); out: bh_unlock_sock(sk); sock_put(sk); }
static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned short reason; if (skb->len < 2) goto out; reason = le16_to_cpu(*(__le16 *)skb->data); skb_pull(skb, 2); scp->discdata_in.opt_status = cpu_to_le16(reason); scp->discdata_in.opt_optl = 0; memset(scp->discdata_in.opt_data, 0, 16); if (skb->len > 0) { u16 dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { scp->discdata_in.opt_optl = cpu_to_le16(dlen); skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen); } } scp->addrrem = cb->src_port; sk->sk_state = TCP_CLOSE; switch(scp->state) { case DN_CI: case DN_CD: scp->state = DN_RJ; sk->sk_err = ECONNREFUSED; break; case DN_RUN: sk->sk_shutdown |= SHUTDOWN_MASK; scp->state = DN_DN; break; case DN_DI: scp->state = DN_DIC; break; } if (!sock_flag(sk, SOCK_DEAD)) { if (sk->sk_socket->state != SS_UNCONNECTED) sk->sk_socket->state = SS_DISCONNECTING; sk->sk_state_change(sk); } if (scp->addrrem) { dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC); } scp->persist_fxn = dn_destroy_timer; scp->persist = dn_nsp_persist(sk); out: kfree_skb(skb); }
static int dn_nsp_retrans_conn_conf(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CC) dn_send_conn_conf(sk, GFP_ATOMIC); return 0; }
static int dn_nsp_retrans_conninit(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) dn_nsp_send_conninit(sk, NSP_RCI); return 0; }
void dn_nsp_delayed_ack(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); if (scp->ackxmt_oth != scp->numoth_rcv) dn_nsp_send_oth_ack(sk); if (scp->ackxmt_dat != scp->numdat_rcv) dn_nsp_send_data_ack(sk); }
static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned short reason; if (skb->len < 2) goto out; reason = dn_ntohs(*(__u16 *)skb->data); skb_pull(skb, 2); scp->discdata_in.opt_status = reason; scp->discdata_in.opt_optl = 0; memset(scp->discdata_in.opt_data, 0, 16); if (skb->len > 0) { unsigned char dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { scp->discdata_in.opt_optl = dlen; memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen); } } scp->addrrem = cb->src_port; sk->state = TCP_CLOSE; switch(scp->state) { case DN_CI: case DN_CD: scp->state = DN_RJ; break; case DN_RUN: sk->shutdown |= SHUTDOWN_MASK; scp->state = DN_DN; break; case DN_DI: scp->state = DN_DIC; break; } if (!sk->dead) { if (sk->socket->state != SS_UNCONNECTED) sk->socket->state = SS_DISCONNECTING; sk->state_change(sk); } dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC); scp->persist_fxn = dn_destroy_timer; scp->persist = dn_nsp_persist(sk); out: kfree_skb(skb); }
static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) { scp->state = DN_CD; scp->persist = 0; } kfree_skb(skb); }
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; }
/* * If one of our conninit messages is returned, this function * deals with it. It puts the socket into the NO_COMMUNICATION * state. */ static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) { scp->state = DN_NC; sk->sk_state = TCP_CLOSE; if (!sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); } kfree_skb(skb); }
void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, unsigned short reason, gfp_t gfp) { struct dn_scp *scp = DN_SK(sk); int ddl = 0; if (msgflg == NSP_DISCINIT) ddl = le16_to_cpu(scp->discdata_out.opt_optl); if (reason == 0) reason = le16_to_cpu(scp->discdata_out.opt_status); dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl, scp->discdata_out.opt_data, scp->addrrem, scp->addrloc); }
void dn_send_conn_ack (struct sock *sk) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_ack_msg *msg; if ((skb = dn_alloc_skb(sk, 3, sk->sk_allocation)) == NULL) return; msg = (struct nsp_conn_ack_msg *)skb_put(skb, 3); msg->msgflg = 0x24; msg->dstaddr = scp->addrrem; dn_nsp_send(skb); }
static __le16 *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); __le16 *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); if (unlikely(oth)) { cb->segnum = scp->numoth; seq_add(&scp->numoth, 1); } else { cb->segnum = scp->numdat; seq_add(&scp->numdat, 1); } *(ptr++) = cpu_to_le16(cb->segnum); return ptr; }
unsigned long dn_nsp_persist(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; t *= nsp_backoff[scp->nsp_rxtshift]; if (t < HZ) t = HZ; if (t > (600*HZ)) t = (600*HZ); if (scp->nsp_rxtshift < NSP_MAXRXTSHIFT) scp->nsp_rxtshift++; /* printk(KERN_DEBUG "rxtshift %lu, t=%lu\n", scp->nsp_rxtshift, t); */ return t; }
unsigned long dn_nsp_persist(struct sock *sk) { struct dn_scp *scp = DN_SK(sk); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; t *= nsp_backoff[scp->nsp_rxtshift]; if (t < HZ) t = HZ; if (t > (600*HZ)) t = (600*HZ); if (scp->nsp_rxtshift < NSP_MAXRXTSHIFT) scp->nsp_rxtshift++; return t; }
/* * disc_conf messages are also called no_resources or no_link * messages depending upon the "reason" field. */ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); unsigned short reason; if (skb->len != 2) goto out; reason = le16_to_cpu(*(__le16 *)skb->data); sk->sk_state = TCP_CLOSE; switch (scp->state) { case DN_CI: scp->state = DN_NR; break; case DN_DR: if (reason == NSP_REASON_DC) scp->state = DN_DRC; if (reason == NSP_REASON_NL) scp->state = DN_CN; break; case DN_DI: scp->state = DN_DIC; break; case DN_RUN: sk->sk_shutdown |= SHUTDOWN_MASK; /* fall through */ case DN_CC: scp->state = DN_CN; } if (!sock_flag(sk, SOCK_DEAD)) { if (sk->sk_socket->state != SS_UNCONNECTED) sk->sk_socket->state = SS_DISCONNECTING; sk->sk_state_change(sk); } scp->persist_fxn = dn_destroy_timer; scp->persist = dn_nsp_persist(sk); out: kfree_skb(skb); }
static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dn_scp *scp = DN_SK(sk); unsigned char *ptr; if (skb->len < 4) goto out; ptr = skb->data; cb->services = *ptr++; cb->info = *ptr++; cb->segsize = le16_to_cpu(*(__le16 *)ptr); if ((scp->state == DN_CI) || (scp->state == DN_CD)) { scp->persist = 0; scp->addrrem = cb->src_port; sk->sk_state = TCP_ESTABLISHED; scp->state = DN_RUN; scp->services_rem = cb->services; scp->info_rem = cb->info; scp->segsize_rem = cb->segsize; if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE) scp->max_window = decnet_no_fc_max_cwnd; if (skb->len > 0) { u16 dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { scp->conndata_in.opt_optl = cpu_to_le16(dlen); skb_copy_from_linear_data_offset(skb, 1, scp->conndata_in.opt_data, dlen); } } dn_nsp_send_link(sk, DN_NOCHANGE, 0); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); } out: kfree_skb(skb); }
static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dn_scp *scp = DN_SK(sk); unsigned char *ptr; if (skb->len < 4) goto out; ptr = skb->data; cb->services = *ptr++; cb->info = *ptr++; cb->segsize = dn_ntohs(*(__u16 *)ptr); if ((scp->state == DN_CI) || (scp->state == DN_CD)) { scp->persist = 0; scp->addrrem = cb->src_port; sk->state = TCP_ESTABLISHED; scp->state = DN_RUN; scp->services_rem = cb->services; scp->info_rem = cb->info; scp->segsize_rem = cb->segsize; if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE) scp->max_window = decnet_no_fc_max_cwnd; if (skb->len > 0) { unsigned char dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { scp->conndata_in.opt_optl = dlen; memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen); } } dn_nsp_send_link(sk, DN_NOCHANGE, 0); if (!sk->dead) sk->state_change(sk); } out: kfree_skb(skb); }