int pktwait(char * app, void * pio) { u_long tmo; tmo = cticks + (3 * TPS); /* 3 second timeout */ if (deflength > (int)lilbufsiz) { while (bigfreeq.q_len < 1) { tk_yield(); if (tmo < cticks) { ns_printf(pio, "%s flood timeout\n", app); return -1; } } } else /* can use a little packet */ { while (lilfreeq.q_len < 1) { tk_yield(); if (tmo < cticks) { ns_printf(pio, "%s flood timeout\n",app); return -1; } } } return 0; }
void tcp_sleep(void * event) { int i; /* search event array for an unused slot */ for (i = 0; i < MAX_EVENTS; i++) { if (tk_eventlist[i].event == 0) /* found a slot */ { tk_eventlist[i].event = event; /* save event to wake up on */ tk_eventlist[i].task = TK_THIS; /* save calling task */ UNLOCK_NET_RESOURCE(NET_RESID); /* free stack mutex */ TK_BLOCK(); /* suspend calling task */ LOCK_NET_RESOURCE(NET_RESID); /* we woke up - reenter stack */ tk_eventlist[i].event = NULL; /* clear array entry */ return; } } /* fall to here if we ran out of free event slots. Best thing to do is * let system spin, then return to caller for another sleep test. */ tcp_no_taskslot++; tk_yield(); }
void tk_kill(task * tk_to_die) { task *tk; if(tk_died) /* Is another task in the process of dying? */ { tk_yield(); /* this should allow it to finish */ if(tk_died) /* Other task still dying? */ { dtrap(); /* system bug */ } } /* hunt for the task which tk_to_die is the successor of */ for (tk = tk_cur; tk->tk_next != tk_to_die; tk = tk->tk_next) ; /* now patch around tk_to_die */ tk->tk_next = tk_to_die->tk_next; /* If I'm killing myself, die the next time I block */ if (tk_cur == tk_to_die) { tk_died = tk_cur; } else tk_del(tk_to_die); }
int tcp_send_an_echo(TCPCLIENT tcpclient) { int e; u_long total; u_long sendsize; u_long starttime; int block; u_long words; /* send data word index */ u_long dataval; u_long sent = 0; /* sent in this loop */ if (tcpclient->ticks > cticks) return TCPE_TIME_NOT_RIPE ; if (tcpclient->sending) /* guard against re-entry */ return TCPE_BLOCKED; tcpclient->sending++; ns_printf(tcpclient->pio,"sending TCP echo %ld to %s\n", tcpclient->send_cnt, print_ipad(tcpclient->rhost)); total = tcpclient->len; block = 0; starttime = cticks; while (total > sent) { tcpclient->ticks = cticks + tcpclient->delay; /* back off time for next send */ sendsize = total - sent; if (sendsize > ECHOBUFSIZE) sendsize = ECHOBUFSIZE; /* write pattern into full-size data for integrity test */ dataval = (tcpclient->tot_sent + sent)/4; /* data for first word of buffer */ for (words = 0; words < (ECHOBUFSIZE/4); words++) *((u_long*)tcpclient->inbuf + words) = dataval++; e = send(tcpclient->sock, tcpclient->inbuf, (int)sendsize, 0); if (e < 0) { e = t_errno(tcpclient->sock); if (e == EWOULDBLOCK) { tk_yield(); continue; } ns_printf(tcpclient->pio,"error %d sending TCP echo number %ld\n", e, tcpclient->send_cnt); ns_printf(tcpclient->pio," on byte %ld\n", e); tcpclient->sending--; return TCPE_SEND_FAILED; } sent += e; if ((block += e) >= ECHOBUFSIZE) { ns_printf(tcpclient->pio, "."); block -= ECHOBUFSIZE; } tk_yield(); /* let other tasks run */ } tcpclient->send_cnt++; /* keep counters current */ tcpclient->tot_sent += sent; ns_printf(tcpclient->pio, "\ntcpecho: echoed %ld bytes", sent); if (total > ECHOBUFSIZE) /* see if we should print performance numbers */ { u_long endticks; u_long bps; int fraction; /* wait for all data to come back */ endticks = cticks + (5*TPS); /* use endticks for timeout */ while ((tcpclient->tot_rcvd < tcpclient->tot_sent) && (cticks > endticks)) { tk_yield(); } endticks = cticks - starttime; if (endticks > 0) /* avoid divide by 0 */ { bps = sent/endticks; /* bytes per tick */ bps *= TPS; /* convert to bytes/Sec */ bps /= 1024; /* KBytes/Sec */ fraction = (int)endticks % TPS; endticks /= TPS; ns_printf(tcpclient->pio, " in %d and %d/%d seconds.\n%ld KBytes/sec", (int)endticks, fraction, TPS, bps); } } ns_printf(tcpclient->pio, "\n"); tcpclient->sending--; /* clear reentry flag */ return SUCCESS; }
int in_reshost(char * host, /* IN - textual IP address or host name */ ip_addr * address, /* OUT - address if successful */ int flags) /* IN - RH_VERBOSE, RH_BLOCK */ { char * cp; /* error holder */ unsigned snbits; /* for pass to parse_ipad() */ #ifdef DNS_CLIENT int e; /* Net error code */ u_long tmo; /* timeout for blocking calls */ int blocking = flags & RH_BLOCK; #endif /* DNS_CLIENT */ int verbose = flags & RH_VERBOSE; cp = parse_ipad(address, &snbits, host); if (!cp) /* worked, string was parsable dot notation */ return 0; #ifndef DNS_CLIENT if (verbose) dprintf("Unable to parse IP host %s.\nerror: %s\n", host, (char*)cp); return ENP_PARAM; #else /* DNS_CLIENT enabled in build */ if (verbose) dprintf("can't parse %s (%s), trying DNS\n", host, cp); tmo = cticks + (5 * TPS); /* set timeout value */ if (dns_servers[0]) /* dont bother if no servers are set */ { if (verbose) dprintf("trying DNS lookup...\n"); e = dns_query(host, address); if (e == ENP_SEND_PENDING) { if (blocking) { while (tmo > cticks) { tk_yield(); e = dns_query(host, address); if (e == 0) goto rh_got_dns; } } if (verbose) dprintf("DNS inquiry sent\n"); return 0; } else if(e == 0) { rh_got_dns: /* DNS resolution worked */ if (verbose) dprintf("active host found via DNS (%u.%u.%u.%u)\n", PUSH_IPADDR(*address)); return 0; } else if(e == ENP_TIMEOUT) /* timeout? */ { if (verbose) dprintf("DNS timeout"); } else { if (verbose) dprintf("DNS error %d", e); } if (verbose) dprintf(", host not set\n"); return e; } if (verbose) dprintf("DNS/host-parse failed.\n"); return ENP_PARAM; #endif /* DNS_CLIENT */ }
void pktdemux() { PACKET pkt; NET ifc; /* interface packet came from */ IFMIB mib; int pkts; char * eth; pkts = 0; /* packets per loop */ while (rcvdq.q_len) { /* If we are low on free packets, don't hog CPU cycles */ if (pkts++ > bigfreeq.q_len) { #ifdef SUPERLOOP return; /* don't hog stack on superloop */ #else /* SUPERLOOP */ tk_yield(); /* let application tasks process received packets */ pkts = 0; /* reset counter */ #endif /* SUPERLOOP else */ } /* If we get receive interupt from the net during this lock, the MAC driver needs to wait or reschedule */ LOCK_NET_RESOURCE(RXQ_RESID); pkt = (PACKET)q_deq(&rcvdq); UNLOCK_NET_RESOURCE(RXQ_RESID); if (!pkt) panic("pktdemux: got null pkt"); ifc = pkt->net; mib = ifc->n_mib; /* maintain mib stats for unicast and broadcast */ if (isbcast(ifc, (u_char*)pkt->nb_buff + ETHHDR_BIAS)) mib->ifInNUcastPkts++; else mib->ifInUcastPkts++; if(mib->ifAdminStatus == NI_DOWN) { LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* dump packet from downed interface */ UNLOCK_NET_RESOURCE(FREEQ_RESID); mib->ifInDiscards++; continue; /* next packet */ } #ifdef NPDEBUG if (*(pkt->nb_buff - ALIGN_TYPE) != 'M' || *(pkt->nb_buff + pkt->nb_blen) != 'M') { dtrap(); panic("pktdemux: corrupt pkt"); } #endif /* NPDEBUG */ #ifdef LOSSY_IO if(NDEBUG & LOSSY_RX) { if(myloss()) { LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* punt packet */ UNLOCK_NET_RESOURCE(FREEQ_RESID); in_lastloss = (int)(cticks & 0x07) - 4; /* pseudo random reset */ continue; /* act as if we sent OK */ } } #endif /* LOSSY_IO */ /* see if driver set pkt->nb_prot and pkt->type */ if((ifc->n_flags & NF_NBPROT) == 0) { /* Set pkt->type and pkt->nb_prot based based on media type. * Some device drivers pass nb_plen as the total length of the * packet, while others subtract the MAC header. The latter is * probably the right thing to do, but because of this historic * inconsistency we don't try to fix it here - the longer size * turns out to be harmless since the IP layer fixes the size * based on the IP header length field. */ switch(ifc->n_mib->ifType) { case ETHERNET: /* get pointer to ethernet header */ eth = (pkt->nb_buff + ETHHDR_BIAS); #ifdef IEEE_802_3 /* see if it's got snap baggage */ if (ET_TYPE_GET(eth) <= 0x0600) { struct snap_hdr *snap; snap = (struct snap_hdr *)(pkt->nb_buff + ETHHDR_SIZE); pkt->type = (unshort)(snap->type); pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh; } else { pkt->type = htons((unshort)ET_TYPE_GET(eth)); pkt->nb_prot = pkt->nb_buff + ETHHDR_SIZE; } #else pkt->type = htons((unshort)ET_TYPE_GET(eth)); pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh; #endif /* IEEE_802_3 */ break; #if defined(USE_PPP) || defined(USE_SLIP) || defined(PROTOCOL_LIBS) case PPP: /* PPP or SLIP over a UART */ case SLIP: pkt->nb_prot = pkt->nb_buff + MaxLnh; pkt->type = IPTP; /* only type our PPP supports */ break; #endif /* USE_PPP || USE_SLIP */ #ifdef USE_PPPOE case PPPOE: /* do not change type yet, for PPPoE */ break; #endif /* USE_PPPOE */ default: /* driver bug? */ dprintf("pktdemux: bad Iface type %ld\n",ifc->n_mib->ifType); LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); UNLOCK_NET_RESOURCE(FREEQ_RESID); continue; } } /* pkt->nb_prot and pkt->type are now set. pass pkt to upper layer */ switch(pkt->type) { case IPTP: /* IP type */ LOCK_NET_RESOURCE(NET_RESID); #ifdef SHARED_IPADDRS add_share_route(pkt); #endif /* SHARED_IPADDRS */ #ifdef IP_V4 ip_rcv(pkt); #else /* don't care, it's IPv4 */ LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); UNLOCK_NET_RESOURCE(FREEQ_RESID); #endif UNLOCK_NET_RESOURCE(NET_RESID); break; #ifdef INCLUDE_ARP case ARPTP: /* ARP type */ LOCK_NET_RESOURCE(NET_RESID); arprcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif /* INCLUDE_ARP */ #ifdef USE_PPPOE case htons(0x8863): case htons(0x8864): LOCK_NET_RESOURCE(NET_RESID); poe_rcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif /* USE_PPPOE */ #ifdef IP_V6 case htons(0x86DD): /* Each received v6 pkt goes thru here exactly once, so set the * outer (first, and usually only) ipv6 header pointer. Tunneled headers * may exist further into the packet. */ pkt->ip6_hdr = (struct ipv6 *)pkt->nb_prot; LOCK_NET_RESOURCE(NET_RESID); ip6_rcv(pkt); UNLOCK_NET_RESOURCE(NET_RESID); break; #endif default: #ifdef NPDEBUG if (NDEBUG & UPCTRACE) dprintf("pktdemux: bad pkt type 0x%04x\n", ntohs(pkt->type)); #endif /* NPDEBUG */ ifc->n_mib->ifInUnknownProtos++; LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* return to free buffer */ UNLOCK_NET_RESOURCE(FREEQ_RESID); break; } continue; } }