For consistency
[gpxe.git] / src / net / ethernet.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdint.h>
20 #include <string.h>
21 #include <byteswap.h>
22 #include <assert.h>
23 #include <vsprintf.h>
24 #include <gpxe/if_arp.h>
25 #include <gpxe/if_ether.h>
26 #include <gpxe/netdevice.h>
27 #include <gpxe/pkbuff.h>
28 #include <gpxe/ethernet.h>
29
30 /** @file
31  *
32  * Ethernet protocol
33  *
34  */
35
36 /** Ethernet broadcast MAC address */
37 static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
38
39 /**
40  * Transmit Ethernet packet
41  *
42  * @v pkb               Packet buffer
43  * @v netdev            Network device
44  * @v net_protocol      Network-layer protocol
45  * @v ll_dest           Link-layer destination address
46  *
47  * Prepends the Ethernet link-layer header and transmits the packet.
48  */
49 static int eth_transmit ( struct pk_buff *pkb, struct net_device *netdev,
50                           struct net_protocol *net_protocol,
51                           const void *ll_dest ) {
52         struct ethhdr *ethhdr = pkb_push ( pkb, sizeof ( *ethhdr ) );
53
54         memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN );
55         memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
56         ethhdr->h_protocol = net_protocol->net_proto;
57         return netdev_transmit ( netdev, pkb );
58 }
59
60 /**
61  * Parse Ethernet link-layer header
62  *
63  * @v pkb       Packet buffer
64  * @v llhdr     Generic link-layer header
65  *
66  * Fills in the generic link-layer header based on information in the
67  * Ethernet link-layer header in the packet buffer.
68  */
69 static void eth_parse_llh ( const struct pk_buff *pkb,
70                             struct ll_header *llhdr ) {
71         struct ethhdr *ethhdr = pkb->data;
72
73         memcpy ( llhdr->dest_ll_addr, ethhdr->h_dest, ETH_ALEN );
74         memcpy ( llhdr->source_ll_addr, ethhdr->h_source, ETH_ALEN );
75         llhdr->net_proto = ethhdr->h_protocol;
76
77         if ( memcmp ( ethhdr->h_dest, eth_broadcast, ETH_ALEN ) == 0 ) {
78                 llhdr->flags = PKT_FL_BROADCAST;
79         } else if ( ethhdr->h_dest[0] & 0x01 ) {
80                 llhdr->flags = PKT_FL_MULTICAST;
81         } else {
82                 llhdr->flags = 0;
83         }
84 }
85
86 /**
87  * Transcribe Ethernet address
88  *
89  * @v ll_addr   Link-layer address
90  * @ret string  Link-layer address in human-readable format
91  */
92 static const char * eth_ntoa ( const void *ll_addr ) {
93         static char buf[18]; /* "00:00:00:00:00:00" */
94         const uint8_t *eth_addr = ll_addr;
95
96         sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x",
97                   eth_addr[0], eth_addr[1], eth_addr[2],
98                   eth_addr[3], eth_addr[4], eth_addr[5] );
99         return buf;
100 }
101
102 /** Ethernet protocol */
103 struct ll_protocol ethernet_protocol = {
104         .name           = "Ethernet",
105         .ll_proto       = htons ( ARPHRD_ETHER ),
106         .ll_addr_len    = ETH_ALEN,
107         .ll_broadcast   = eth_broadcast,
108         .transmit       = eth_transmit,
109         .parse_llh      = eth_parse_llh,
110         .ntoa           = eth_ntoa,
111 };
112
113 LL_PROTOCOL ( ethernet_protocol );