00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdint.h>
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <byteswap.h>
00025 #include <errno.h>
00026 #include <assert.h>
00027 #include <gpxe/if_arp.h>
00028 #include <gpxe/if_ether.h>
00029 #include <gpxe/in.h>
00030 #include <gpxe/netdevice.h>
00031 #include <gpxe/iobuf.h>
00032 #include <gpxe/ethernet.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041 static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static int eth_push ( struct net_device *netdev __unused,
00054 struct io_buffer *iobuf, const void *ll_dest,
00055 const void *ll_source, uint16_t net_proto ) {
00056 struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
00057
00058
00059 memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN );
00060 memcpy ( ethhdr->h_source, ll_source, ETH_ALEN );
00061 ethhdr->h_protocol = net_proto;
00062
00063 return 0;
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 static int eth_pull ( struct net_device *netdev __unused,
00077 struct io_buffer *iobuf, const void **ll_dest,
00078 const void **ll_source, uint16_t *net_proto ) {
00079 struct ethhdr *ethhdr = iobuf->data;
00080
00081
00082 if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
00083 DBG ( "Ethernet packet too short (%zd bytes)\n",
00084 iob_len ( iobuf ) );
00085 return -EINVAL;
00086 }
00087
00088
00089 iob_pull ( iobuf, sizeof ( *ethhdr ) );
00090
00091
00092 *ll_dest = ethhdr->h_dest;
00093 *ll_source = ethhdr->h_source;
00094 *net_proto = ethhdr->h_protocol;
00095
00096 return 0;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 void eth_init_addr ( const void *hw_addr, void *ll_addr ) {
00106 memcpy ( ll_addr, hw_addr, ETH_ALEN );
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 const char * eth_ntoa ( const void *ll_addr ) {
00116 static char buf[18];
00117 const uint8_t *eth_addr = ll_addr;
00118
00119 sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x",
00120 eth_addr[0], eth_addr[1], eth_addr[2],
00121 eth_addr[3], eth_addr[4], eth_addr[5] );
00122 return buf;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 int eth_mc_hash ( unsigned int af, const void *net_addr, void *ll_addr ) {
00134 const uint8_t *net_addr_bytes = net_addr;
00135 uint8_t *ll_addr_bytes = ll_addr;
00136
00137 switch ( af ) {
00138 case AF_INET:
00139 ll_addr_bytes[0] = 0x01;
00140 ll_addr_bytes[1] = 0x00;
00141 ll_addr_bytes[2] = 0x5e;
00142 ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f;
00143 ll_addr_bytes[4] = net_addr_bytes[2];
00144 ll_addr_bytes[5] = net_addr_bytes[3];
00145 return 0;
00146 default:
00147 return -ENOTSUP;
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 int eth_eth_addr ( const void *ll_addr, void *eth_addr ) {
00158 memcpy ( eth_addr, ll_addr, ETH_ALEN );
00159 return 0;
00160 }
00161
00162
00163 struct ll_protocol ethernet_protocol __ll_protocol = {
00164 .name = "Ethernet",
00165 .ll_proto = htons ( ARPHRD_ETHER ),
00166 .hw_addr_len = ETH_ALEN,
00167 .ll_addr_len = ETH_ALEN,
00168 .ll_header_len = ETH_HLEN,
00169 .push = eth_push,
00170 .pull = eth_pull,
00171 .init_addr = eth_init_addr,
00172 .ntoa = eth_ntoa,
00173 .mc_hash = eth_mc_hash,
00174 .eth_addr = eth_eth_addr,
00175 };
00176
00177
00178
00179
00180
00181
00182
00183 struct net_device * alloc_etherdev ( size_t priv_size ) {
00184 struct net_device *netdev;
00185
00186 netdev = alloc_netdev ( priv_size );
00187 if ( netdev ) {
00188 netdev->ll_protocol = ðernet_protocol;
00189 netdev->ll_broadcast = eth_broadcast;
00190 netdev->max_pkt_len = ETH_FRAME_LEN;
00191 }
00192 return netdev;
00193 }