• No se han encontrado resultados

Fundamentación teórica y antecedentes

1.1. Las Funciones Ejecutivas

1.1.3. Inhibición

1.1.3.1. Posturas multidimensionales sobre la inhibición

4.5.1 Searching The ARP Cache

The network interface code that handles output uses ARP to resolve IP addresses into the corresponding hardware addresses. In particular, the network output process calls procedure arpfind to search the ARP cache and find an entry that matches a given protocol address.

/* arpfind.c - sendarp */

#include <conf.h>

#include <kernel.h>

#include <network.h>

* arpfind - find an ARP entry given a protocol address and interface */

struct arpentry *arpfind(pra, prtype, pni) char *pra;

int prtype;

struct netif *pni;

{

struct arpentry *pae;

int i;

for (i=0; i<ARP_TSIZE; ++i) { pae = &arptable[i];

if (pae->ae_state == AS_FREE) continue;

if (pae->ae_prtype == prtype &&

pae->ae_pni == pni &&

blkequ(pae->ae_pra, pra, pae->ae_prlen)) return pae;

}

return 0;

}

Argument pra points to a high-level (protocol) address that must be resolved, argument prtype gives the type of the address (using the standard ARP values for protocol types), and argument pni points to a network interface structure. Arpfind searches the ARP cache sequentially until it finds an entry that matches the specified address. It returns a pointer to the entry.

Recall that our design places all ARP bindings in a single table. For technologies like Ethernet, where hardware addresses are globally unique, a single table does not present a problem. However, some technologies allow reuse of hardware addresses on given hardware address (e.g., address 5) in its cache. Argument pni insures that arpfind will select bindings that correspond to the correct network interface. Conceptually, our implementation uses the combination of a network interface number and hardware address to uniquely identify an entry in the table.

4.5.2 Broadcasting An ARP Request

Once an ARP cache entry has been allocated for a given IP address, the network interface software calls procedure arpsend to format and broadcast an ARP request for the corresponding hardware address.

/* arpsend.c - arpsend */

#include <conf.h>

#include <kernel.h>

#include <network.h>

* arpsend - broadcast an ARP request

* N.B. Assumes interrupts disabled

*/

int arpsend(pae)

struct arpentry *pae;

{

struct netif *pni = pae->ae_pni;

struct ep *pep;

struct arp *parp;

int arplen;

pep = (struct ep *) getbuf(Net.netpool);

if (pep == SYSERR) return SYSERR;

blkcopy(pep->ep_dst, pni->ni_hwb.ha_addr, pae->ae_hwlen);

pep->ep_type = EPT_ARP;

parp = (struct arp *) pep->ep_data;

parp->ar_hwtype = hs2net(pae->ae_hwtype);

parp->ar_prtype = hs2net(pae->ae_prtype);

parp->ar_hwlen = pae->ae_hwlen;

parp->ar_prlen = pae->ae_prlen;

parp->ar_op = hs2net(AR_REQUEST);

blkcopy(SHA(parp), pni->ni_hwa.ha_addr, pae->ae_hwlen);

blkcopy(SPA(parp), pni->ni_ip, pae->ae_prlen);

bzero(THA(parp), pae->ae_hwlen);

blkcopy(TPA(parp), pae->ae_pra, pae->ae_prlen);

arplen = sizeof(struct arp) + 2*(parp->ar_hwlen + parp->ar_prlen);

write(pni->ni_dev, pep, arplen);

return OK;

}

Arpsend takes a pointer to an entry in the cache as an argument, forms an ARP request for the IP address in that entry, and transmits the request. The code is much simpler than it appears. After allocating a buffer to hold the packed, arpsend fills in each field, obtaining most of the needed information from the arp cache entry given by argument pae. It uses the hardware broadcast for the packet destination address and specifies that the packet is an ARP request (AR_REQUEST). After the hardware and protocol address length fields have been assigned, arpsend can use in-line procedures SHA, SPA, THA, and TPA to compute the locations in the ARP packet of the variable-length address fields.

After arpsend creates the ARP request packet, it invokes system call write to send it.

4.5.3 Output Procedure

Procedure netwrite accepts packets for transmission on a given network interface.

/* netwrite.c - netwrite */

#include <conf.h>

#include <kernel.h>

#include <network.h>

#include <q.h>

struct arpentry *arpalloc(), *arpfind();

* netwrite - write a packet on an interface, using ARP if needed

*/

int netwrite(pni, pep, len) struct netif *pni;

struct ep *pep;

int len;

{

struct arpentry *pae;

STATWORD ps;

int i;

if (pni->ni_state != NIS_UP) { freebuf(pep);

return SYSERR;

}

pep->ep_len = len;

if (pni == &nif[NI_LOCAL]) return local_out(pep);

else if (isbrc(pep->ep_nexthop)) {

blkcopy(pep->ep_dst, pni->ni_hwb.ha_addr, EP_ALEN);

write(pni->ni_dev, pep, len);

return OK;

}

/* else, look up the protocol address... */

disable(ps);

pae = arpfind(pep->ep_nexthop, pep->ep_type, pni);

if (pae && pae->ae_state == AS_RESOLVED) {

blkcopy(pep->ep_dst, pae->ae_hwa, pae->ae_hwlen);

restore(ps);

return write(pni->ni_dev, pep, len);

}

if (IP_CLASSD(pep->ep_nexthop)) { restore(ps);

return SYSERR;

}

if (pae == 0) { pae = arpalloc();

pae->ae_hwtype = AR_HARDWARE;

pae->ae_prtype = EPT_IP;

pae->ae_hwlen = EP_ALEN;

pae->ae_prlen = IP_ALEN;

pae->ae_pni = pni;

pae->ae_queue = EMPTY;

blkcopy(pae->ae_pra, pep->ep_nexthop, pae->ae_prlen);

pae->ae_attempts = 0;

pae->ae_ttl = ARP_RESEND;

arpsend(pae);

}

if (pae->ae_queue == EMPTY)

pae->ae_queue = newq(ARP_QSIZE, QF_NOWAIT);

if (enq(pae->ae_queue, pep, 0) < 0) freebuf(pep);

restore(ps);

return OK;

}

Netwrite calls arpfind to look up an entry in the cache for the destination address. If the entry has been resolved, netwrite copies the hardware address into the packet and calls write to transmit the packet. If the entry has not been resolved and is not pending, netwrite calls arpalloc to allocate an ARP request. It then fills in fields in the ARP entry, and calls arpsend to broadcast the request.

Because netwrite must return to its caller without delay, it leaves packets awaiting address resolution on the queue of packets associated with the ARP cache entry for that address. It first checks to see if a queue exists. If one is needed, it calls newq to create a queue. Finally, netwrite calls enq to enqueue the packet for transmission later, after the address has been resolved. Each output queue has a finite size. If the queue is full when netwrite needs to enqueue a packet, netwrite discards the packet.