int pkt_test_upcall (void) { #if !defined(NO_RMODE_CALL) int i, max = RX_BUFS + 3; for (i = 0; i < max; i++) { eth_Packet eth; IREGS regs; DWORD linear = 0; memset (®s, 0, sizeof(regs)); memset (ð, 0, sizeof(eth)); eth.head.type = IP4_TYPE; memset (ð.head.destination, 0xFF, 6); memcpy (ð.head.source, _eth_addr, 6); #if (DOSX & (PHARLAP|X32VM)) rmc.eax = 0; rmc.ebx = _pkt_inf->handle; rmc.ecx = ETH_MAX; #endif regs.r_cx = ETH_MAX; regs.r_bx = _pkt_inf->handle; regs.r_ax = 0; regs.r_cs = _pkt_inf->rm_seg; regs.r_ip = PktReceiver; if (DPMI_REAL_CALL(®s)) { linear = SEG_OFS_ADDR (regs.r_es, regs.r_di); printf ("Upcall AX=0: ES:DI %04X:%04X\n", (WORD)regs.r_es, (WORD)regs.r_di); #if (DOSX & DJGPP) if (linear) dosmemput (ð, (WORD)regs.r_cx, linear); #elif (DOSX & (DOS4GW|X32VM)) if (linear) memcpy ((void*)linear, ð, (WORD)regs.r_cx); #elif (DOSX & (PHARLAP|POWERPAK)) if (linear) { RP_SET (linear, regs.r_es, regs.r_di); WriteRealMem (linear, ð, (WORD)regs.r_cx); } #else #error Help me! #endif } if (linear) { regs.r_ss = regs.r_sp = 0; regs.r_ax = 1; regs.r_cs = _pkt_inf->rm_seg; regs.r_ip = PktReceiver; regs.r_ds = regs.r_es; regs.r_si = regs.r_di; if (DPMI_REAL_CALL(®s)) printf ("Upcall AX=1\n"); } printf ("buffers used %d, dropped %lu\n", pkt_buffers_used(), pkt_rx_dropped()); } #endif pkt_dump_real_mem(); return (0); }
/** * Enqueue a link-layer frame (IPv4/v6 only) to the internal loopback device. * * \note This function uses call-by-value. Thus `pkt' buffer can * be modified by loopback_device() and loopback handler may * send using _eth_send(). * * \note Loopback device cannot send to itself (potential recursion). */ static int send_loopback (link_Packet pkt, BOOL is_ip6, unsigned *err_line) { struct pkt_ringbuf *q; const in_Header *ip; int ip_len; SIO_TRACE (("send_loopback")); if (!_pkt_inf) { *err_line = __LINE__; goto drop_it; } /* Call loopback handler with IP-packet */ ip = (in_Header*) ((BYTE*)&pkt + _pkt_ip_ofs); ip_len = loopback_device ((in_Header*)ip); q = &_pkt_inf->pkt_queue; if (!q || ip_len > (int)_mtu) { *err_line = __LINE__; goto drop_it; } if (ip_len > 0) { #if defined(USE_FAST_PKT) /* * Don't let pkt_receiver() modify the queue while testing/copying. */ if (pkt_buffers_used() >= _pkt_inf->pkt_queue.num_buf - 1) { *err_line = __LINE__; goto drop_it; } { char tx_buf [ETH_MAX]; unsigned len = ip_len; /* Enqueue packet to head of input IP-queue. */ if (!_pktserial) { void *data = (*mac_tx_format) (tx_buf, _eth_addr, is_ip6 ? IP6_TYPE : IP4_TYPE); memcpy (MAC_SRC(data), &_eth_loop_addr, sizeof(mac_address)); memcpy (data, ip, ip_len); len += _pkt_ip_ofs; } else memcpy (tx_buf, ip, ip_len); if (!pkt_append_recv(tx_buf, len)) { *err_line = __LINE__; goto drop_it; } } #elif defined(WIN32) struct pkt_rx_element *head; ENTER_CRIT(); if (pktq_in_index(q) == q->out_index) /* queue is full, drop it */ { q->num_drop++; LEAVE_CRIT(); *err_line = __LINE__; goto drop_it; } head = (struct pkt_rx_element*) pktq_in_buf (q); head->rx_length = _pkt_ip_ofs + ip_len; gettimeofday (&head->tstamp_put, NULL); /* Enqueue packet to head of input IP-queue. */ if (!_pktserial) { void *data = (*mac_tx_format) (&head->rx_buf, _eth_addr, is_ip6 ? IP6_TYPE : IP4_TYPE); memcpy (MAC_SRC(data), &_eth_loop_addr, sizeof(mac_address)); memcpy (data, ip, ip_len); } else memcpy (head, ip, ip_len); /* Update queue head index */ q->in_index = pktq_in_index (q); LEAVE_CRIT(); #else union link_Packet *head; DISABLE(); if (pktq_in_index(q) == q->out_index) /* queue is full, drop it */ { q->num_drop++; ENABLE(); *err_line = __LINE__; goto drop_it; } head = (union link_Packet*) pktq_in_buf (q); /* Enqueue packet to head of input IP-queue. */ if (!_pktserial) { void *data = (*mac_tx_format) (head, _eth_addr, is_ip6 ? IP6_TYPE : IP4_TYPE); memcpy (MAC_SRC(data), &_eth_loop_addr, sizeof(mac_address)); memcpy (data, ip, ip_len); } else memcpy (head, ip, ip_len); /* Update queue head index */ q->in_index = pktq_in_index (q); ENABLE(); #endif } *err_line = 0; return (ip_len + _pkt_ip_ofs); drop_it: /* * Maybe this should be an input counter */ if (is_ip6) STAT (ip6stats.ip6s_odropped++); else STAT (ip4stats.ips_odropped++); return (0); }