49 const int PCAP_SNAPLEN = 0xFFFF;
50 const int PCAP_PROMISC = 1;
52 const int AddressType = AF_PACKET;
54 const std::string DEVICE_PREFIX =
"";
56 const int PCAP_TIMEOUT = 0;
58 struct sockaddr_ll_t {
72 EthernetTransport(id, pPlatformService),
78 memset(&macAddr_, 0x0,
sizeof(macAddr_));
88 if (pPcapHandle_ != NULL)
90 pcap_close(pPcapHandle_);
114 "Device to use as the raw packet entry point.");
116 configRegistrar.registerNumeric<std::uint64_t>(
"bitrate",
119 "Transport bitrate in bps. This is the total allowable" 120 " throughput for the transport combined in both directions" 121 " (upstream and downstream). A value of 0 disables the" 122 " bitrate feature.");
124 configRegistrar.registerNumeric<
bool>(
"broadcastmodeenable",
127 "Broadcast all packets to all NEMs.");
130 configRegistrar.registerNumeric<
bool>(
"arpcacheenable",
133 "Enable ARP request/reply monitoring to map Ethernet address to NEM.");
141 for(
const auto & item : update)
143 if(item.first ==
"bitrate")
146 u64BitRate_ = item.second[0].asUINT64();
150 "TRANSPORTI %03hu Transports::Raw::RawTransport %s %s: %ju",
156 else if(item.first ==
"device")
158 sTargetDevice_ = item.second[0].asString();
162 "TRANSPORTI %03hu RawTransport %s %s: %s",
166 sTargetDevice_.c_str());
168 else if(item.first ==
"broadcastmodeenable")
174 "TRANSPORTI %03d RawTransport %s %s: %d",
180 else if(item.first ==
"arpcacheenable")
186 "TRANSPORTI %03d RawTransport %s %s: %d",
194 throw makeException<ConfigureException>(
"RawTransport: " 195 "Unexpected configuration item %s",
206 bool bMacResolved{
false};
209 char errbuf[PCAP_ERRBUF_SIZE]={};
212 struct pcap_if *iflist;
215 std::string sDeviceName = DEVICE_PREFIX;
218 if (pcap_findalldevs (&iflist, errbuf) < 0 || iflist == NULL)
220 std::stringstream ssDescription;
221 ssDescription<<
"could not get interface list "<< errbuf<<std::ends;
227 struct pcap_if *ifp = iflist;
233 if(sTargetDevice_ == ifp->name)
236 sDeviceName += ifp->name;
239 pcap_addr_t *ap = ifp->addresses;
242 while (ap && !bMacResolved)
245 if(ap->addr->sa_family == AddressType)
247 struct sockaddr_ll_t *s = (
struct sockaddr_ll_t *) ap->addr;
253 "TRANSPORTI %03d RawTransport %s adapter %s, hw addr %s",
271 pcap_freealldevs(iflist);
274 if(bMacResolved ==
false)
276 std::stringstream ssDescription;
277 ssDescription<<
"could not resolve our mac address "<< sTargetDevice_ <<
" " << errbuf<<std::ends;
282 if((pPcapHandle_ = pcap_open_live(sDeviceName.c_str(), PCAP_SNAPLEN, PCAP_PROMISC, PCAP_TIMEOUT, errbuf)) == NULL)
284 std::stringstream ssDescription;
285 ssDescription<<
"could not open device "<< sDeviceName <<
" " << errbuf<<std::ends;
290 if(pcap_set_datalink(pPcapHandle_, DLT_EN10MB) < 0)
292 std::stringstream ssDescription;
293 ssDescription<<
"could not set datalink type on device "<< sDeviceName <<
" " << errbuf<<std::ends;
298 if(pcap_setdirection(pPcapHandle_, PCAP_D_IN) < 0)
300 std::stringstream ssDescription;
301 ssDescription<<
"could not set direction on device "<< sDeviceName <<
" " << errbuf<<std::ends;
308 thread_ = std::thread(&RawTransport::readDevice,
this);
316 if(thread_.joinable())
346 "TRANSPORTI %03d RawTransport %s ethernet frame error",
351 handleUpstreamControl(msgs);
363 if(pcap_sendpacket(pPcapHandle_, (
const std::uint8_t*) pkt.
get(), pkt.
length()) < 0)
367 "TRANSPORTI %03d RawTransport %s pcap_sendpacket error %s",
370 pcap_geterr(pPcapHandle_));
376 "TRANSPORTI %03d RawTransport %s src %hu, dst %hu, dscp %hhu, length %zu",
380 pktInfo.getDestination(),
381 pktInfo.getPriority(),
385 const size_t sizePending = pBitPool_->
get(pkt.
length() * 8);
392 "TRANSPORTI %03d RawTransport %s bitpool request error %zd of %zd",
395 sizePending, pkt.
length() * 8);
403 handleUpstreamControl(msgs);
406 void EMANE::Transports::Raw::RawTransport::handleUpstreamControl(
const ControlMessages & msgs)
408 for(
const auto & pMessage : msgs)
410 switch(pMessage->getId())
414 const auto pSerializedControlMessage =
417 switch(pSerializedControlMessage->getSerializedId())
422 "TRANSPORTI %03hu RawTransport::%s unknown serialized msg id %hu, ignore",
425 pSerializedControlMessage->getSerializedId());
434 "TRANSPORTI %03hu RawTransport::%s unknown msg id %hu, ignore",
444 void EMANE::Transports::Raw::RawTransport::readDevice()
446 const std::uint8_t* buf = NULL;
448 struct pcap_pkthdr *pcap_hdr = NULL;
455 iPcapResult = pcap_next_ex(pPcapHandle_, &pcap_hdr, &buf);
462 "TRANSPORTI %03d RawTransport %s pcap_next_ex error %s",
465 pcap_geterr(pPcapHandle_));
471 else if (iPcapResult == 0)
476 else if(iPcapResult == 1)
483 "TRANSPORTI %03d RawTransport %s frame error",
491 NEMId nemDestination;
496 if(
parseFrame(pEtherHeader, nemDestination, dscp) < 0)
500 "TRANSPORTI %03d RawTransport %s frame parse error",
508 "TRANSPORTI %03d RawTransport %s src %hu, dst %hu, dscp %hhu, length %u",
522 const size_t sizePending = pBitPool_->
get(pcap_hdr->caplen * 8);
529 "TRANSPORTI %03d RawTransport %s bitpool request error %zd of %u",
533 pcap_hdr->caplen * 8);
A Packet class that allows upstream processing to strip layer headers as the packet travels up the st...
Implementation of a rate limiting bit pool.
The Registrar interface provides access to all of the emulator registrars.
A Serialized Control Message is used to encapsulate Serializable control messages as they traverse pr...
DECLARE_TRANSPORT(EMANE::Transports::Raw::RawTransport)
void configure(const ConfigurationUpdate &items) override
virtual ConfigurationRegistrar & configurationRegistrar()=0
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
struct EtherAddrBytes bytes
RawTransport(NEMId id, PlatformServiceProvider *pPlatformService)
std::list< const ControlMessage * > ControlMessages
void registerNonNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
void setMaxSize(std::uint64_t u64NewSize)
virtual int parseFrame(const Utils::EtherHeader *pEthHeader, EMANE::NEMId &dst, std::uint8_t &dscp)
struct sockaddr_in_t __attribute__((__may_alias__))
Store source, destination, creation time and priority information for a packet.
std::uint16_t sll_protocol
void initialize(Registrar ®istrar) override
void processUpstreamPacket(UpstreamPacket &pkt, const ControlMessages &msgs) override
const PacketInfo & getPacketInfo() const
Specialized packet the allows downstream processing to add layer specific headers as the packet trave...
int cancel(std::thread &thread)
std::uint64_t get(std::uint64_t u64Request, bool bFullFill=true)
Raw Device EMANE Transport.
const std::uint16_t ETH_ALEN
Ethernet hardware address length.
Component start exception is used to indicate an exception during transition to the start state...
virtual int verifyFrame(const void *buf, size_t len)
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
std::string ethaddr_to_string(const EtherAddr *addr)
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
void sendDownstreamPacket(DownstreamPacket &pkt, const ControlMessages &msgs=empty)
void updateArpCache(const Utils::EtherHeader *pEthHeader, EMANE::NEMId nemId)
std::uint8_t buff[ETH_ALEN]
void processUpstreamControl(const ControlMessages &msgs) override
std::uint32_t sll_ifindex