2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
6 #include <boot/net/Ethernet.h>
9 #include <KernelExport.h>
11 #include <boot/net/ChainBuffer.h>
14 //#define TRACE_ETHERNET
16 # define TRACE(x) dprintf x
22 // #pragma mark - EthernetInterface
25 EthernetInterface::EthernetInterface()
26 : fIPAddress(INADDR_ANY
)
31 EthernetInterface::~EthernetInterface()
37 EthernetInterface::IPAddress() const
44 EthernetInterface::SetIPAddress(ip_addr_t ipAddress
)
46 fIPAddress
= ipAddress
;
50 // #pragma mark - EthernetSubService
53 EthernetSubService::EthernetSubService(const char *serviceName
)
54 : NetService(serviceName
)
59 EthernetSubService::~EthernetSubService()
64 // #pragma mark - EthernetService
67 EthernetService::EthernetService()
68 : NetService(kEthernetServiceName
),
76 EthernetService::~EthernetService()
79 fInterface
->FreeSendReceiveBuffer(fSendBuffer
);
84 EthernetService::Init(EthernetInterface
*interface
)
89 fInterface
= interface
;
91 fSendBuffer
= fInterface
->AllocateSendReceiveBuffer(
92 SEND_BUFFER_SIZE
+ RECEIVE_BUFFER_SIZE
);
95 fReceiveBuffer
= (uint8
*)fSendBuffer
+ SEND_BUFFER_SIZE
;
102 EthernetService::MACAddress() const
104 return fInterface
->MACAddress();
109 EthernetService::IPAddress() const
111 return fInterface
->IPAddress();
116 EthernetService::SetIPAddress(ip_addr_t ipAddress
)
118 fInterface
->SetIPAddress(ipAddress
);
123 EthernetService::Send(const mac_addr_t
&destination
, uint16 protocol
,
126 TRACE(("EthernetService::Send(to: %012llx, proto: 0x%hx, %lu bytes)\n",
127 destination
.ToUInt64(), protocol
, (buffer
? buffer
->TotalSize() : 0)));
129 if (!fInterface
|| !fSendBuffer
)
132 // sending has time, but we need to handle incoming packets as soon as
134 ProcessIncomingPackets();
140 size_t dataSize
= buffer
->TotalSize();
141 if (dataSize
> ETHER_MAX_TRANSFER_UNIT
)
144 // prepend ethernet header
146 ChainBuffer
headerBuffer(&header
, sizeof(header
), buffer
);
147 header
.source
= fInterface
->MACAddress();
148 header
.destination
= destination
;
149 header
.type
= htons(protocol
);
152 size_t totalSize
= headerBuffer
.TotalSize();
153 headerBuffer
.Flatten(fSendBuffer
);
155 // pad data, if necessary
156 if (dataSize
< ETHER_MIN_TRANSFER_UNIT
) {
157 size_t paddingSize
= ETHER_MIN_TRANSFER_UNIT
- dataSize
;
158 memset((uint8
*)fSendBuffer
+ totalSize
, 0, paddingSize
);
159 totalSize
+= paddingSize
;
163 ssize_t bytesSent
= fInterface
->Send(fSendBuffer
, totalSize
);
166 if (bytesSent
!= (ssize_t
)totalSize
)
172 // ProcessIncomingPackets
174 EthernetService::ProcessIncomingPackets()
176 if (!fInterface
|| !fReceiveBuffer
)
180 // read from the interface
181 ssize_t bytesReceived
= fInterface
->Receive(fReceiveBuffer
,
182 RECEIVE_BUFFER_SIZE
);
183 if (bytesReceived
< 0)
186 // basic sanity checks (packet too small/too big)
188 < (ssize_t
)sizeof(ether_header
) + ETHER_MIN_TRANSFER_UNIT
190 > (ssize_t
)sizeof(ether_header
) + ETHER_MAX_TRANSFER_UNIT
) {
194 // is the packet intended for us?
195 ether_header
*header
= (ether_header
*)fReceiveBuffer
;
196 if (header
->destination
!= kBroadcastMACAddress
197 && header
->destination
!= fInterface
->MACAddress()) {
201 TRACE(("EthernetService::ProcessIncomingPackets(): received ethernet "
202 "frame: to: %012llx, proto: 0x%hx, %ld bytes\n",
203 header
->destination
.ToUInt64(), ntohs(header
->type
),
204 bytesReceived
- (ssize_t
)sizeof(ether_header
)));
206 // find a service handling this kind of packet
207 int serviceCount
= fServices
.Count();
208 for (int i
= 0; i
< serviceCount
; i
++) {
209 EthernetSubService
*service
= fServices
.ElementAt(i
);
210 if (service
->EthernetProtocol() == ntohs(header
->type
)) {
211 service
->HandleEthernetPacket(this, header
->destination
,
212 (uint8
*)fReceiveBuffer
+ sizeof(ether_header
),
213 bytesReceived
- sizeof(ether_header
));
220 // RegisterEthernetSubService
222 EthernetService::RegisterEthernetSubService(EthernetSubService
*service
)
224 return (service
&& fServices
.Add(service
) == B_OK
);
227 // UnregisterEthernetSubService
229 EthernetService::UnregisterEthernetSubService(EthernetSubService
*service
)
231 return (service
&& fServices
.Remove(service
) >= 0);
234 // CountSubNetServices
236 EthernetService::CountSubNetServices() const
238 return fServices
.Count();
243 EthernetService::SubNetServiceAt(int index
) const
245 return fServices
.ElementAt(index
);