Exemple #1
0
static int send_request(struct net_device *dev, uint16_t pro,
		uint8_t pln, const void *spa, const void *tpa) {
	int ret;
	struct sk_buff *skb;
	struct net_header_info hdr_info;

	skb = skb_alloc(dev->hdr_len
			+ ARP_CALC_HEADER_SIZE(dev->addr_len, pln));
	if (skb == NULL) {
		return -ENOMEM;
	}

	skb->dev = dev;
	skb->nh.raw = skb->mac.raw + dev->hdr_len;

	hdr_info.type = ETH_P_ARP;
	hdr_info.src_hw = &dev->dev_addr[0];
	hdr_info.dst_hw = &dev->broadcast[0];
	assert(dev->ops != NULL);
	assert(dev->ops->build_hdr != NULL);
	ret = dev->ops->build_hdr(skb, &hdr_info);
	if (ret != 0) {
		skb_free(skb);
		return ret;
	}

	arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln,
			ARP_OP_REQUEST, &dev->dev_addr[0], spa,
			&dev->broadcast[0], tpa);

	return net_tx(skb, NULL);
}
Exemple #2
0
void process_icmp(ether_header_t *ether, ip_header_t *ip, icmp_header_t *icmp)
{
  unsigned int i;
  unsigned char tmp[6];

  memset(pkt_buf, 0, ntohs(ip->length) + (ntohs(ip->length)%2) - 4*(ip->version_ihl & 0x0f));

  /* check icmp checksum */
  i = icmp->checksum;
  icmp->checksum = 0;
  memcpy(pkt_buf, icmp, ntohs(ip->length) - 4*(ip->version_ihl & 0x0f));
  icmp->checksum = checksum((unsigned short *)pkt_buf, (ntohs(ip->length)+1)/2 - 2*(ip->version_ihl & 0x0f));
  if (i != icmp->checksum)
    return;
  
  if (icmp->type == 8) { /* echo request */
    icmp->type = 0; /* echo reply */
    /* swap src and dest hw addresses */
    memcpy(tmp, ether->dest, 6);
    memcpy(ether->dest, ether->src, 6);
    memcpy(ether->src, tmp, 6);
    /* swap src and dest ip addresses */
    memcpy(&i, &ip->src, 4);
    memcpy(&ip->src, &ip->dest, 4);
    memcpy(&ip->dest, &i, 4);
    /* recompute ip header checksum */
    ip->checksum = 0;
    ip->checksum = checksum((unsigned short *)ip, 2*(ip->version_ihl & 0x0f));
    /* recompute icmp checksum */
    icmp->checksum = 0;
    icmp->checksum = checksum((unsigned short *)icmp, ntohs(ip->length)/2 - 2*(ip->version_ihl & 0x0f));
    /* transmit */
    net_tx(ether, ETHER_H_LEN + ntohs(ip->length), 1);
  }
}
Exemple #3
0
int process_broadcast(unsigned char *pkt, int len)
{
    ether_header_t *ether_header = (ether_header_t *)pkt;
    arp_header_t *arp_header = (arp_header_t *)(pkt + ETHER_H_LEN);
    unsigned char tmp[10];
    unsigned int ip = htonl(our_ip);

    if (ether_header->type[1] != 0x06) /* ARP */
      {
	return -1;
      }

    /* hardware address space = ethernet */
    if (arp_header->hw_addr_space != 0x0100)
	return -1;

    /* protocol address space = IP */
    if (arp_header->proto_addr_space != 0x0008)
	return -1;

    if (arp_header->opcode == 0x0100) { /* arp request */
	if (our_ip == 0) /* return if we don't know our ip */
	    return -1;

	int i;
/* 	printf("ARP request : "); */
/* 	for (i=0; i<4; i++) */
/* 	  printf("%d ", arp_header->proto_target[i]); */
/* 	printf("\n"); */

	if (!memcmp(arp_header->proto_target, &ip, 4)) { /* for us */
	  
/* 	  printf("ARP our IP : %x\n", ip); */

	    /* put src hw address into dest hw address */
	    memcpy(ether_header->dest, ether_header->src, 6);
	    /* put our hw address into src hw address */
	    memcpy(ether_header->src, eth_mac, 6);
	    arp_header->opcode = 0x0200; /* arp reply */
	    /* swap sender and target addresses */
	    memcpy(tmp, arp_header->hw_sender, 10);
	    memcpy(arp_header->hw_sender, arp_header->hw_target, 10);
	    memcpy(arp_header->hw_target, tmp, 10);
	    /* put our hw address into sender hw address */
	    memcpy(arp_header->hw_sender, eth_mac, 6);
	    /* transmit */
	    net_tx(pkt, ETHER_H_LEN + ARP_H_LEN, 1);
	}
    }

    return 0;
}
Exemple #4
0
static int ndp_xmit(struct sk_buff *skb,
		struct net_device *dev) {
	struct net_header_info hdr_info;

	assert(skb != NULL);
	assert(dev != NULL);

	hdr_info.type = ETH_P_IPV6;
	hdr_info.src_hw = dev->dev_addr;
	hdr_info.dst_hw = dev->broadcast;

	return net_tx(skb, &hdr_info);
}
Exemple #5
0
/**
 * Look up media-specific link-layer address in the ARP cache
 *
 * @v netdev		Network device
 * @v net_protocol	Network-layer protocol
 * @v dest_net_addr	Destination network-layer address
 * @v source_net_addr	Source network-layer address
 * @ret dest_ll_addr	Destination link layer address
 * @ret rc		Return status code
 *
 * This function will use the ARP cache to look up the link-layer
 * address for the link-layer protocol associated with the network
 * device and the given network-layer protocol and addresses.  If
 * found, the destination link-layer address will be filled in in @c
 * dest_ll_addr.
 *
 * If no address is found in the ARP cache, an ARP request will be
 * transmitted on the specified network device and -ENOENT will be
 * returned.
 */
int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol,
		  const void *dest_net_addr, const void *source_net_addr,
		  void *dest_ll_addr ) {
	struct ll_protocol *ll_protocol = netdev->ll_protocol;
	const struct arp_entry *arp;
	struct io_buffer *iobuf;
	struct arphdr *arphdr;
	int rc;

	/* Look for existing entry in ARP table */
	arp = arp_find_entry ( ll_protocol, net_protocol, dest_net_addr );
	if ( arp ) {
		DBG ( "ARP cache hit: %s %s => %s %s\n",
		      net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
		      ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
		memcpy ( dest_ll_addr, arp->ll_addr, ll_protocol->ll_addr_len);
		return 0;
	}
	DBG ( "ARP cache miss: %s %s\n", net_protocol->name,
	      net_protocol->ntoa ( dest_net_addr ) );

	/* Allocate ARP packet */
	iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
			  2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) );
	if ( ! iobuf )
		return -ENOMEM;
	iob_reserve ( iobuf, MAX_LL_HEADER_LEN );

	/* Build up ARP request */
	arphdr = iob_put ( iobuf, sizeof ( *arphdr ) );
	arphdr->ar_hrd = ll_protocol->ll_proto;
	arphdr->ar_hln = ll_protocol->ll_addr_len;
	arphdr->ar_pro = net_protocol->net_proto;
	arphdr->ar_pln = net_protocol->net_addr_len;
	arphdr->ar_op = htons ( ARPOP_REQUEST );
	memcpy ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
		 netdev->ll_addr, ll_protocol->ll_addr_len );
	memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
		 source_net_addr, net_protocol->net_addr_len );
	memset ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
		 0, ll_protocol->ll_addr_len );
	memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
		 dest_net_addr, net_protocol->net_addr_len );

	/* Transmit ARP request */
	if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol,
			     netdev->ll_broadcast, netdev->ll_addr ) ) != 0 )
		return rc;

	return -ENOENT;
}
Exemple #6
0
static int eth_txts(uint8 *pkt, int len)
{
  int res;
  int oldirq;
  for( ; ; ) {
    if (!irq_inside_int())
      tx_lock();
#if 0
    STOPIRQ;
    while (bba_dma_busy) {
      STARTIRQ;
      thd_pass();
      STOPIRQ;
    }
#endif

#ifdef NICE
    res = net_tx(pkt, len, irq_inside_int());
#else
    res = net_tx(pkt, len, 1);
#endif

#if 0
    STARTIRQ;
#endif

    if (!irq_inside_int())
      tx_unlock();

    if (!res || irq_inside_int())
      break;
 
    thd_pass();
  }

  return res;
}
Exemple #7
0
/**
 * Process incoming marker packet
 *
 * @v iobuf		I/O buffer
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int eth_slow_marker_rx ( struct io_buffer *iobuf,
				struct net_device *netdev ) {
	union eth_slow_packet *eth_slow = iobuf->data;
	struct eth_slow_marker *marker = &eth_slow->marker;

	eth_slow_marker_dump ( iobuf, netdev, "RX" );

	if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
		/* Send marker response */
		marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
		eth_slow_marker_dump ( iobuf, netdev, "TX" );
		return net_tx ( iobuf, netdev, &eth_slow_protocol,
				eth_slow_address, netdev->ll_addr );
	} else {
		/* Discard all other marker packets */
		free_iob ( iobuf );
		return -EINVAL;
	}
}
Exemple #8
0
static int eth_txts(uint8 *pkt, int len)
{
  int res;
  for( ; ; ) {
    if (!irq_inside_int())
      tx_lock();

    res = net_tx(pkt, len, irq_inside_int());

    if (!irq_inside_int())
      tx_unlock();

    if (!res || irq_inside_int())
      break;
 
    thd_pass();
  }

  return res;
}
Exemple #9
0
int driver_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct net_device_stats *stats = (struct net_device_stats*) netdev_priv(dev);
	int len                        = skb->len;
	void* addr                     = skb->data;

	/* transmit to nic-session */
	while (net_tx(addr, len)) {
		/* tx queue is  full, could not enqueue packet */
		printk("TX full\n");
	}

	dev_kfree_skb(skb);

	/* save timestamp */
	dev->trans_start = jiffies;

	stats->tx_packets++;
	stats->tx_bytes += len;

 	return NETDEV_TX_OK;
}
Exemple #10
0
/**
 * Process incoming LACP packet
 *
 * @v iobuf		I/O buffer
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int eth_slow_lacp_rx ( struct io_buffer *iobuf,
			      struct net_device *netdev ) {
	union eth_slow_packet *eth_slow = iobuf->data;
	struct eth_slow_lacp *lacp = &eth_slow->lacp;

	eth_slow_lacp_dump ( iobuf, netdev, "RX" );

	/* Build response */
	memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
	memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
	memset ( &lacp->collector, 0, sizeof ( lacp->collector ) );
	lacp->collector.tlv.type = ETH_SLOW_TLV_LACP_COLLECTOR;
	lacp->collector.tlv.length = ETH_SLOW_TLV_LACP_COLLECTOR_LEN;
	memcpy ( &lacp->partner, &lacp->actor, sizeof ( lacp->partner ) );
	lacp->partner.tlv.type = ETH_SLOW_TLV_LACP_PARTNER;
	lacp->partner.tlv.length = ETH_SLOW_TLV_LACP_PARTNER_LEN;
	memset ( &lacp->partner.reserved, 0,
		 sizeof ( lacp->partner.reserved ) );
	memset ( &lacp->actor, 0, sizeof ( lacp->actor ) );
	lacp->actor.tlv.type = ETH_SLOW_TLV_LACP_ACTOR;
	lacp->actor.tlv.length = ETH_SLOW_TLV_LACP_ACTOR_LEN;
	lacp->actor.system_priority = htons ( LACP_SYSTEM_PRIORITY_MAX );
	memcpy ( lacp->actor.system, netdev->ll_addr,
		 sizeof ( lacp->actor.system ) );
	lacp->actor.key = htons ( 1 );
	lacp->actor.port_priority = htons ( LACP_PORT_PRIORITY_MAX );
	lacp->actor.port = htons ( 1 );
	lacp->actor.state = ( LACP_STATE_IN_SYNC |
			      LACP_STATE_COLLECTING |
			      LACP_STATE_DISTRIBUTING |
			      ( lacp->partner.state & LACP_STATE_FAST ) );
	lacp->header.version = ETH_SLOW_LACP_VERSION;

	/* Send response */
	eth_slow_lacp_dump ( iobuf, netdev, "TX" );
	return net_tx ( iobuf, netdev, &eth_slow_protocol, eth_slow_address,
			netdev->ll_addr );
}
Exemple #11
0
static int ip6_xmit(struct sk_buff *skb) {
	const struct in6_addr *daddr;
	struct net_header_info hdr_info;

	assert(skb != NULL);
	assert(skb->nh.iph != NULL);
	daddr = &skb->nh.ip6h->daddr;

	hdr_info.type = ETH_P_IPV6;
	hdr_info.src_hw = NULL;
	hdr_info.dst_hw = NULL;

	/* FIXME */
	assert(skb->dev != NULL);
	if (skb->dev->flags & IFF_LOOPBACK) {
		hdr_info.dst_p = NULL;
	}
	else {
		hdr_info.dst_p = daddr;
		hdr_info.p_len = sizeof *daddr;
	}

	return net_tx(skb, &hdr_info);
}
Exemple #12
0
/**
 * Send AoE command
 *
 * @v aoe		AoE session
 * @ret rc		Return status code
 *
 * This transmits an AoE command packet.  It does not wait for a
 * response.
 */
static int aoe_send_command ( struct aoe_session *aoe ) {
	struct ata_command *command = aoe->command;
	struct io_buffer *iobuf;
	struct aoehdr *aoehdr;
	union aoecmd *aoecmd;
	struct aoeata *aoeata;
	unsigned int count;
	unsigned int data_out_len;
	unsigned int aoecmdlen;

	/* Fail immediately if we have no netdev to send on */
	if ( ! aoe->netdev ) {
		aoe_done ( aoe, -ENETUNREACH );
		return -ENETUNREACH;
	}

	/* If we are transmitting anything that requires a response,
         * start the retransmission timer.  Do this before attempting
         * to allocate the I/O buffer, in case allocation itself
         * fails.
         */
	start_timer ( &aoe->timer );

	/* Calculate count and data_out_len for this subcommand */
	switch ( aoe->aoe_cmd_type ) {
	case AOE_CMD_ATA:
		count = command->cb.count.native;
		if ( count > AOE_MAX_COUNT )
			count = AOE_MAX_COUNT;
		data_out_len = ( command->data_out ?
				 ( count * ATA_SECTOR_SIZE ) : 0 );
		aoecmdlen = sizeof ( aoecmd->ata );
		break;
	case AOE_CMD_CONFIG:
		count = 0;
		data_out_len = 0;
		aoecmdlen = sizeof ( aoecmd->cfg );
		break;
	default:
		return -ENOTSUP;
	}

	/* Create outgoing I/O buffer */
	iobuf = alloc_iob ( ETH_HLEN + sizeof ( *aoehdr ) +
			    aoecmdlen + data_out_len );

	if ( ! iobuf )
		return -ENOMEM;
	iob_reserve ( iobuf, ETH_HLEN );
	aoehdr = iob_put ( iobuf, sizeof ( *aoehdr ) );
	aoecmd = iob_put ( iobuf, aoecmdlen );
	memset ( aoehdr, 0, ( sizeof ( *aoehdr ) + aoecmdlen ) );

	/* Fill AoE header */
	aoehdr->ver_flags = AOE_VERSION;
	aoehdr->major = htons ( aoe->major );
	aoehdr->minor = aoe->minor;
	aoehdr->command = aoe->aoe_cmd_type;
	aoehdr->tag = htonl ( ++aoe->tag );

	/* Fill AoE payload */
	switch ( aoe->aoe_cmd_type ) {
	case AOE_CMD_ATA:
		/* Fill AoE command */
		aoeata = &aoecmd->ata;
		linker_assert ( AOE_FL_DEV_HEAD	== ATA_DEV_SLAVE,
				__fix_ata_h__ );
		aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 )|
				   ( command->cb.device & ATA_DEV_SLAVE ) |
				   ( data_out_len ? AOE_FL_WRITE : 0 ) );
		aoeata->err_feat = command->cb.err_feat.bytes.cur;
		aoeata->count = count;
		aoeata->cmd_stat = command->cb.cmd_stat;
		aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
		if ( ! command->cb.lba48 )
			aoeata->lba.bytes[3] |=
				( command->cb.device & ATA_DEV_MASK );

		/* Fill data payload */
		copy_from_user ( iob_put ( iobuf, data_out_len ),
				 command->data_out, aoe->command_offset,
				 data_out_len );
		break;
	case AOE_CMD_CONFIG:
		/* Nothing to do */
		break;
	default:
		assert ( 0 );
	}

	/* Send packet */
	return net_tx ( iobuf, aoe->netdev, &aoe_protocol, aoe->target );
}