diff --git a/vanetza/common/channel.hpp b/vanetza/common/channel.hpp new file mode 100644 index 000000000..0d86a4f12 --- /dev/null +++ b/vanetza/common/channel.hpp @@ -0,0 +1,34 @@ +#ifndef CHANNEL_HPP +#define CHANNEL_HPP + +#include + +namespace vanetza +{ + +using Channel = int; + +namespace channel +{ + +/** + * Channel assigned for ETSI ITS + * \see TS 102 965 V1.3.1 Annex A + */ +constexpr Channel SCH0 = 180; +constexpr Channel CCH = SCH0; + +constexpr Channel SCH1 = 176; +constexpr Channel SCH2 = 178; + +constexpr Channel SCH3 = 174; +constexpr Channel SCH4 = 172; + +constexpr Channel SCH5 = 182; +constexpr Channel SCH6 = 184; + +} // namespace channel +} // namespace vanetza + +#endif /* CHANNEL_HPP */ + diff --git a/vanetza/geonet/data_request.hpp b/vanetza/geonet/data_request.hpp index 32d62d106..def6c4e65 100644 --- a/vanetza/geonet/data_request.hpp +++ b/vanetza/geonet/data_request.hpp @@ -1,6 +1,7 @@ #ifndef DATA_REQUEST_HPP_3JYISVXB #define DATA_REQUEST_HPP_3JYISVXB +#include #include #include #include @@ -45,6 +46,7 @@ struct DataRequest boost::optional repetition; unsigned max_hop_limit; TrafficClass traffic_class; + Channel channel; }; /** diff --git a/vanetza/geonet/link_layer.hpp b/vanetza/geonet/link_layer.hpp index 8ef24bf1b..2b3fa3795 100644 --- a/vanetza/geonet/link_layer.hpp +++ b/vanetza/geonet/link_layer.hpp @@ -1,6 +1,7 @@ #ifndef LINK_LAYER_HPP_F2JBRUTL #define LINK_LAYER_HPP_F2JBRUTL +#include #include namespace vanetza @@ -12,6 +13,7 @@ struct LinkLayer { MacAddress sender; MacAddress destination; + Channel channel; }; } // namespace geonet diff --git a/vanetza/geonet/location_table.cpp b/vanetza/geonet/location_table.cpp index 822a0959d..9547aea76 100644 --- a/vanetza/geonet/location_table.cpp +++ b/vanetza/geonet/location_table.cpp @@ -9,9 +9,33 @@ namespace geonet static_assert(std::numeric_limits::has_quiet_NaN, "quiet NaN value unavailable"); +LinkInfoEntry::LinkInfoEntry(const Runtime& rt) : + m_runtime(rt), + m_pdr(std::numeric_limits::quiet_NaN()), m_pdr_update(rt.now()) +{ +} + +void LinkInfoEntry::update_pdr(std::size_t packet_size, double beta) +{ + using namespace vanetza::units; + + if (std::isnan(m_pdr)) { + m_pdr = 0.0; + m_pdr_update = m_runtime.now(); + } else if (beta > 0.0 && beta < 1.0) { + const std::chrono::duration time_period = m_runtime.now() - m_pdr_update; + if (time_period.count() > 0.0) { + double instant_pdr = packet_size / time_period.count(); + m_pdr *= beta; + m_pdr += (1.0 - beta) * instant_pdr; + m_pdr_update = m_runtime.now(); + } + } +} + LocationTableEntry::LocationTableEntry(const Runtime& rt) : m_runtime(rt), m_is_neighbour(false), m_has_position_vector(false), - m_pdr(std::numeric_limits::quiet_NaN()), m_pdr_update(rt.now()) + m_link_info(rt, LinkInfoEntryCreator(rt)) { } @@ -25,27 +49,27 @@ const Address& LocationTableEntry::geonet_address() const return m_position_vector.gn_addr; } -const MacAddress& LocationTableEntry::link_layer_address() const +const MacAddress& LocationTableEntry::link_layer_address(Channel channel) const { - return geonet_address().mid(); + auto link_info = m_link_info.get_value_ptr(channel); + return link_info->link_layer_address(); } -void LocationTableEntry::update_pdr(std::size_t packet_size, double beta) +bool LocationTableEntry::has_channel(Channel channel) const { - using namespace vanetza::units; + return m_link_info.has_value(channel); +} - if (std::isnan(m_pdr)) { - m_pdr = 0.0; - m_pdr_update = m_runtime.now(); - } else if (beta > 0.0 && beta < 1.0) { - const std::chrono::duration time_period = m_runtime.now() - m_pdr_update; - if (time_period.count() > 0.0) { - double instant_pdr = packet_size / time_period.count(); - m_pdr *= beta; - m_pdr += (1.0 - beta) * instant_pdr; - m_pdr_update = m_runtime.now(); - } - } +double LocationTableEntry::get_pdr(Channel channel) const +{ + auto link_info = m_link_info.get_value_ptr(channel); + return link_info->get_pdr(); +} + +void LocationTableEntry::update_pdr(Channel channel, std::size_t packet_size, double beta) +{ + LinkInfoEntry& link_info = m_link_info.get_value(channel); + link_info.update_pdr(packet_size, beta); } void LocationTableEntry::set_position_vector(const LongPositionVector& pv) @@ -54,6 +78,14 @@ void LocationTableEntry::set_position_vector(const LongPositionVector& pv) m_position_vector = pv; } +void LocationTableEntry::add_link(const Channel channel, const MacAddress& mac) +{ + m_link_info.drop_expired(); + LinkInfoEntry& link_info = m_link_info.get_value(channel); + link_info.set_link_layer_address(mac); + link_info.set_channel(channel); +} + bool LocationTableEntry::update_position_vector(const LongPositionVector& lpv) { if (has_position_vector()) { @@ -76,14 +108,15 @@ void LocationTableEntry::set_neighbour(bool flag) LocationTable::LocationTable(const MIB& mib, Runtime& rt) : - m_table(rt, LocationTableEntryCreator(rt)) + m_table(rt, LocationTableEntryCreator(rt)), + m_link_table(rt) { m_table.set_lifetime(std::chrono::seconds(mib.itsGnLifetimeLocTE / units::si::seconds)); } bool LocationTable::has_entry(const Address& addr) const { - return m_table.has_value(addr.mid()); + return m_table.has_value(addr); } bool LocationTable::has_neighbours() const @@ -98,15 +131,38 @@ bool LocationTable::has_neighbours() const return found_neighbour; } +bool LocationTable::has_neighbours(Channel channel) const +{ + bool found_neighbour = false; + for (const auto& entry : m_table.map()) { + if (entry.second.is_neighbour()) { + if (entry.second.has_channel(channel)) { + found_neighbour = true; + break; + } + } + } + return found_neighbour; +} + auto LocationTable::neighbours() const -> neighbour_range { const entry_predicate neighbour_predicate = - [](const MacAddress&, const LocationTableEntry& entry) { + [](const Address&, const LocationTableEntry& entry) { return entry.is_neighbour(); }; return filter(neighbour_predicate); } +auto LocationTable::neighbours(Channel channel) const -> neighbour_range +{ + const entry_predicate neighbour_predicate = + [channel](const Address&, const LocationTableEntry& entry) { + return entry.has_channel(channel); + }; + return filter(neighbour_predicate); +} + auto LocationTable::filter(const entry_predicate& predicate) const -> entry_range { using namespace boost::adaptors; @@ -124,15 +180,30 @@ void LocationTable::visit(const entry_visitor& visitor) const } } +void LocationTable::drop_expired() +{ + m_link_table.drop_expired(); + m_table.drop_expired(); +} + +void LocationTable::update(const Channel channel, const MacAddress& mac, const Address& addr) +{ + LocationTableEntry& entry = m_table.get_value(addr); + entry.add_link(channel, mac); + + LinkTableEntry& link_entry = m_link_table.get_value(mac); + link_entry.set_geonet_address(addr); +} + LocationTableEntry& LocationTable::update(const LongPositionVector& lpv) { - LocationTableEntry* entry = m_table.get_value_ptr(lpv.gn_addr.mid()); + LocationTableEntry* entry = m_table.get_value_ptr(lpv.gn_addr); if (entry && entry->has_position_vector()) { if (entry->update_position_vector(lpv)) { - m_table.refresh(lpv.gn_addr.mid()); + m_table.refresh(lpv.gn_addr); } } else { - entry = &m_table.refresh(lpv.gn_addr.mid()); + entry = &m_table.refresh(lpv.gn_addr); entry->update_position_vector(lpv); } return *entry; @@ -140,39 +211,42 @@ LocationTableEntry& LocationTable::update(const LongPositionVector& lpv) LocationTableEntry& LocationTable::get_or_create_entry(const Address& addr) { - return m_table.get_value(addr.mid()); + return m_table.get_value(addr); } LocationTableEntry& LocationTable::get_or_create_entry(const MacAddress& mac) { - return m_table.get_value(mac); + auto addr = m_link_table.get_value(mac); + return m_table.get_value(addr.geonet_address()); } const LocationTableEntry* LocationTable::get_entry(const Address& addr) const { - return m_table.get_value_ptr(addr.mid()); + return m_table.get_value_ptr(addr); } const LocationTableEntry* LocationTable::get_entry(const MacAddress& mac) const { - return m_table.get_value_ptr(mac); + auto addr = m_link_table.get_value_ptr(mac); + return m_table.get_value_ptr(addr->geonet_address()); } const LongPositionVector* LocationTable::get_position(const Address& addr) const -{ - return get_position(addr.mid()); -} - -const LongPositionVector* LocationTable::get_position(const MacAddress& mac) const { const LongPositionVector* position = nullptr; - auto* entry = m_table.get_value_ptr(mac); + auto* entry = m_table.get_value_ptr(addr); if (entry && entry->has_position_vector()) { position = &entry->get_position_vector(); } return position; } +const LongPositionVector* LocationTable::get_position(const MacAddress& mac) const +{ + auto addr = m_link_table.get_value_ptr(mac); + return get_position(addr->geonet_address()); +} + } // namespace geonet } // namespace vanetza diff --git a/vanetza/geonet/location_table.hpp b/vanetza/geonet/location_table.hpp index eb3a33c46..401c020f7 100644 --- a/vanetza/geonet/location_table.hpp +++ b/vanetza/geonet/location_table.hpp @@ -2,6 +2,7 @@ #define LOCATION_TABLE_HPP_EMPVZSHQ #include +#include #include #include #include @@ -15,20 +16,58 @@ namespace vanetza namespace geonet { +class LinkInfoEntry +{ +public: + LinkInfoEntry(const Runtime& rt); + + const MacAddress& link_layer_address() const { return m_link_layer_address; } + void set_link_layer_address(const MacAddress& mac) { m_link_layer_address = mac; } + + const Channel channel() const { return m_channel; } + void set_channel(const Channel channel) { m_channel = channel; } + + double get_pdr() const { return m_pdr; } + void update_pdr(std::size_t packet_size, double beta = 0.5); + +private: + MacAddress m_link_layer_address; + Channel m_channel; + + double m_pdr; /*< packet data rate in bytes per second */ + Clock::time_point m_pdr_update; + + const Runtime& m_runtime; +}; + +class LinkInfoEntryCreator +{ +public: + LinkInfoEntryCreator(const Runtime& rt) : m_runtime(rt) {} + LinkInfoEntry operator()() { return LinkInfoEntry(m_runtime); } + +private: + const Runtime& m_runtime; +}; + class LocationTableEntry { public: + using link_info_table_type = SoftStateMap; + LocationTableEntry(const Runtime& rt); const Address& geonet_address() const; - const MacAddress& link_layer_address() const; + const MacAddress& link_layer_address(Channel channel) const; + bool has_channel(Channel channel) const; StationType station_type() const; /** * Get packed data rate (PDR) of corresponding source. + * \param channel desired channel * \return PDR in bytes per second, might be not-a-number */ - double get_pdr() const { return m_pdr; } + double get_pdr(Channel channel) const; /** * Update packet data rate. @@ -36,7 +75,7 @@ class LocationTableEntry * \param packet_size received number of bytes * \param beta weight factor for exponential moving average ]0; 1[ */ - void update_pdr(std::size_t packet_size, double beta = 0.5); + void update_pdr(Channel channel, std::size_t packet_size, double beta = 0.5); /** * Check if position vector has been set before @@ -58,6 +97,8 @@ class LocationTableEntry */ bool update_position_vector(const LongPositionVector& pv); + void add_link(const Channel channel, const MacAddress& address); + /** * Check if this entry belongs to a direct neighbour * \return true if direct neighbour @@ -83,8 +124,8 @@ class LocationTableEntry bool m_is_neighbour; bool m_has_position_vector; LongPositionVector m_position_vector; - double m_pdr; /*< packet data rate in bytes per second */ - Clock::time_point m_pdr_update; + + link_info_table_type m_link_info; }; class LocationTableEntryCreator @@ -97,6 +138,16 @@ class LocationTableEntryCreator const Runtime& m_runtime; }; +class LinkTableEntry +{ +public: + const Address& geonet_address() const { return m_geonet_address; } + void set_geonet_address(const Address& addr) { m_geonet_address = addr; } + +private: + Address m_geonet_address; +}; + /** * GeoNetworking LocationTable * See section 7.1 of EN 302 636-4-1 for details. @@ -104,9 +155,9 @@ class LocationTableEntryCreator class LocationTable { public: - using table_type = SoftStateMap; - using entry_visitor = std::function; - using entry_predicate = std::function; + using table_type = SoftStateMap; + using entry_visitor = std::function; + using entry_predicate = std::function; using entry_range = boost::select_second_const_range< boost::filtered_range< @@ -114,8 +165,11 @@ class LocationTable const typename table_type::map_range>>; using neighbour_range = entry_range; + using link_table_type = SoftStateMap; + LocationTable(const MIB&, Runtime&); bool has_entry(const Address&) const; + void update(const Channel, const MacAddress&, const Address&); LocationTableEntry& update(const LongPositionVector&); LocationTableEntry& get_or_create_entry(const Address&); LocationTableEntry& get_or_create_entry(const MacAddress&); @@ -124,13 +178,16 @@ class LocationTable const LongPositionVector* get_position(const Address&) const; const LongPositionVector* get_position(const MacAddress&) const; bool has_neighbours() const; + bool has_neighbours(Channel) const; neighbour_range neighbours() const; + neighbour_range neighbours(Channel) const; entry_range filter(const entry_predicate&) const; void visit(const entry_visitor&) const; - void drop_expired() { m_table.drop_expired(); } + void drop_expired(); private: table_type m_table; + link_table_type m_link_table; }; } // namespace geonet diff --git a/vanetza/geonet/router.cpp b/vanetza/geonet/router.cpp index b5cfb6e9d..5932bbbc6 100644 --- a/vanetza/geonet/router.cpp +++ b/vanetza/geonet/router.cpp @@ -38,10 +38,12 @@ struct ControlInfo { ControlInfo(const DataRequest request) : communication_profile(request.communication_profile), - its_aid(request.its_aid) {} + its_aid(request.its_aid), + channel(request.channel) {} const CommunicationProfile communication_profile; const ItsAid its_aid; + const Channel channel; }; template @@ -119,7 +121,6 @@ const uint16be_t ether_type = host_cast(0x8947); Router::Router(Runtime& rt, const MIB& mib) : m_mib(mib), m_runtime(rt), - m_request_interface(&DummyDccRequestInterface::get()), m_security_entity(nullptr), m_location_table(mib, m_runtime), m_bc_forward_buffer(mib.itsGnBcForwardingPacketBufferSize * 1024), @@ -133,6 +134,8 @@ Router::Router(Runtime& rt, const MIB& mib) : { // send BEACON immediately after start-up at next runtime trigger invocation reset_beacon_timer(Clock::duration::zero()); + + set_access_interfaces(AccessInterfaceList{std::make_tuple(channel::CCH, MacAddress(), &DummyDccRequestInterface::get())}); } Router::~Router() @@ -170,12 +173,6 @@ void Router::set_security_entity(security::SecurityEntity* entity) m_security_entity = entity; } -void Router::set_access_interface(dcc::RequestInterface* ifc) -{ - m_request_interface = (ifc == nullptr ? &DummyDccRequestInterface::get() : ifc); - assert(m_request_interface != nullptr); -} - void Router::set_address(const Address& addr) { m_local_position_vector.gn_addr = addr; @@ -186,6 +183,22 @@ void Router::set_random_seed(std::uint_fast32_t seed) m_random_gen.seed(seed); } +void Router::set_access_interfaces(AccessInterfaceList ifc_list) +{ + m_channel_mac_map.clear(); + m_mac_interface_map.clear(); + + for (auto ifc : ifc_list) { + Channel channel; + MacAddress mac; + dcc::RequestInterface* interface; + std::tie(channel, mac, interface) = ifc; + + m_channel_mac_map.insert(std::make_pair(channel, mac)); + m_mac_interface_map.insert(std::make_pair(mac, interface)); + } +} + DataConfirm Router::request(const ShbDataRequest& request, DownPacketPtr payload) { DataConfirm result; @@ -223,7 +236,8 @@ DataConfirm Router::request(const ShbDataRequest& request, DownPacketPtr payload execute_media_procedures(ctrl.communication_profile); // step 6: pass packet down to link layer with broadcast destination - pass_down(cBroadcastMacAddress, std::move(pdu), std::move(payload)); + const auto source = m_channel_mac_map.at(ctrl.channel); + pass_down(source, cBroadcastMacAddress, std::move(pdu), std::move(payload)); // step 7: reset beacon timer reset_beacon_timer(); @@ -232,7 +246,7 @@ DataConfirm Router::request(const ShbDataRequest& request, DownPacketPtr payload PendingPacket packet(std::make_tuple(std::move(pdu), std::move(payload)), transmit); // step 3: store & carry forwarding - if (request.traffic_class.store_carry_forward() && !m_location_table.has_neighbours()) { + if (request.traffic_class.store_carry_forward() && !m_location_table.has_neighbours(request.channel)) { PacketBuffer::data_ptr data { new PendingPacketBufferData(std::move(packet)) }; m_bc_forward_buffer.push(std::move(data), m_runtime.now()); } else { @@ -270,7 +284,7 @@ DataConfirm Router::request(const GbcDataRequest& request, DownPacketPtr payload pdu->common().payload = payload->size(); ControlInfo ctrl(request); - auto transmit = [this, ctrl](Packet&& packet, const MacAddress& mac) { + auto transmit = [this, ctrl](Packet&& packet, const MacAddress& destination) { std::unique_ptr pdu; std::unique_ptr payload; std::tie(pdu, payload) = std::move(packet); @@ -290,7 +304,8 @@ DataConfirm Router::request(const GbcDataRequest& request, DownPacketPtr payload execute_media_procedures(ctrl.communication_profile); // step 8: pass PDU to link layer - pass_down(mac, std::move(pdu), std::move(payload)); + const auto source = m_channel_mac_map.at(ctrl.channel); + pass_down(source, destination, std::move(pdu), std::move(payload)); }; auto forwarding = [this, transmit](Packet&& packet) { @@ -305,7 +320,7 @@ DataConfirm Router::request(const GbcDataRequest& request, DownPacketPtr payload // step 2: check if neighbours are present const bool scf = request.traffic_class.store_carry_forward(); - if (scf && !m_location_table.has_neighbours()) { + if (scf && !m_location_table.has_neighbours(request.channel)) { PacketBuffer::data_ptr data { new PendingPacketBufferData(std::move(packet)) }; m_bc_forward_buffer.push(std::move(data), m_runtime.now()); } else { @@ -330,7 +345,7 @@ DataConfirm Router::request(const TsbDataRequest&, DownPacketPtr) return DataConfirm(DataConfirm::ResultCode::REJECTED_UNSPECIFIED); } -void Router::indicate(UpPacketPtr packet, const MacAddress& sender, const MacAddress& destination) +void Router::indicate(UpPacketPtr packet, const MacAddress& sender, const MacAddress& destination, const Channel channel) { assert(packet); @@ -361,6 +376,7 @@ void Router::indicate(UpPacketPtr packet, const MacAddress& sender, const MacAdd IndicationContext::LinkLayer link_layer; link_layer.sender = sender; link_layer.destination = destination; + link_layer.channel = channel; UpPacket* packet_ptr = packet.get(); indication_visitor visitor(*this, link_layer, std::move(packet)); @@ -603,10 +619,10 @@ NextHop Router::forwarding_algorithm_selection(PendingPacketForwarding&& packet, case UnicastForwarding::UNSPECIFIED: // fall through to greedy forwarding case UnicastForwarding::GREEDY: - nh = greedy_forwarding(std::move(packet)); + nh = greedy_forwarding(std::move(packet), ll); break; case UnicastForwarding::CBF: - nh = non_area_contention_based_forwarding(std::move(packet), ll ? &ll->sender : nullptr); + nh = non_area_contention_based_forwarding(std::move(packet), ll ? &ll->sender : nullptr, ll->channel); break; default: throw std::runtime_error("unhandled non-area forwarding algorithm"); @@ -656,17 +672,18 @@ void Router::pass_down(const dcc::DataRequest& request, PduPtr pdu, DownPacketPt } (*payload)[OsiLayer::Network] = ByteBufferConvertible(std::move(pdu)); - assert(m_request_interface); - m_request_interface->request(request, std::move(payload)); + auto request_interface = m_mac_interface_map.at(request.source); + assert(request_interface); + request_interface->request(request, std::move(payload)); } -void Router::pass_down(const MacAddress& addr, PduPtr pdu, DownPacketPtr payload) +void Router::pass_down(const MacAddress& src_addr, const MacAddress& dst_addr, PduPtr pdu, DownPacketPtr payload) { assert(pdu); dcc::DataRequest request; - request.destination = addr; - request.source = m_local_position_vector.gn_addr.mid(); + request.destination = dst_addr; + request.source = src_addr; request.dcc_profile = map_tc_onto_profile(pdu->common().traffic_class); request.ether_type = geonet::ether_type; request.lifetime = std::chrono::seconds(pdu->basic().lifetime.decode() / units::si::seconds); @@ -696,7 +713,9 @@ void Router::on_beacon_timer_expired() } execute_media_procedures(m_mib.itsGnIfType); - pass_down(cBroadcastMacAddress, std::move(pdu), std::move(payload)); + + auto source = m_channel_mac_map.at(channel::CCH); + pass_down(source, cBroadcastMacAddress, std::move(pdu), std::move(payload)); reset_beacon_timer(); } @@ -726,7 +745,7 @@ void Router::dispatch_repetition(const DataRequestVariant& request, std::unique_ boost::apply_visitor(dispatcher, request); } -NextHop Router::greedy_forwarding(PendingPacketForwarding&& packet) +NextHop Router::greedy_forwarding(PendingPacketForwarding&& packet, const LinkLayer* ll) { NextHop nh; GeodeticPosition dest = packet.pdu().extended().position(); @@ -734,10 +753,10 @@ NextHop Router::greedy_forwarding(PendingPacketForwarding&& packet) units::Length mfr_dist = own; MacAddress mfr_addr; - for (auto& neighbour : m_location_table.neighbours()) { + for (auto& neighbour : m_location_table.neighbours(ll->channel)) { const units::Length dist = distance(dest, neighbour.get_position_vector().position()); if (dist < mfr_dist) { - mfr_addr = neighbour.link_layer_address(); + mfr_addr = neighbour.link_layer_address(ll->channel); mfr_dist = dist; } } @@ -747,8 +766,8 @@ NextHop Router::greedy_forwarding(PendingPacketForwarding&& packet) } else { const bool scf = packet.pdu().common().traffic_class.store_carry_forward(); if (scf) { - std::function greedy_fwd = [this](PendingPacketForwarding&& packet) { - NextHop nh = greedy_forwarding(std::move(packet)); + std::function greedy_fwd = [this, ll](PendingPacketForwarding&& packet) { + NextHop nh = greedy_forwarding(std::move(packet), ll); std::move(nh).process(); }; PendingPacket greedy_packet(std::move(packet), greedy_fwd); @@ -763,7 +782,7 @@ NextHop Router::greedy_forwarding(PendingPacketForwarding&& packet) return nh; } -NextHop Router::non_area_contention_based_forwarding(PendingPacketForwarding&& packet, const MacAddress* sender) +NextHop Router::non_area_contention_based_forwarding(PendingPacketForwarding&& packet, const MacAddress* sender, Channel channel) { NextHop nh; const GeoBroadcastHeader& gbc = packet.pdu().extended(); @@ -879,9 +898,9 @@ NextHop Router::area_advanced_forwarding(PendingPacketForwarding&& packet, const nh.buffer(); } } else { - if (ll->destination == m_local_position_vector.gn_addr.mid()) { + if (m_mac_interface_map.find(ll->destination) != m_mac_interface_map.end()) { // continue with greedy forwarding - nh = greedy_forwarding(packet.duplicate()); + nh = greedy_forwarding(packet.duplicate(), ll); // optimization: avoid "double broadcast" if (nh.valid() && nh.mac() == cBroadcastMacAddress) { // contending without further broadcasting @@ -942,15 +961,16 @@ bool Router::process_extended(const ExtendedPduConstRefs& pdu, const const Address& source_addr = shb.source_position.gn_addr; // step 3: execute duplicate address detection (see 9.2.1.5) - detect_duplicate_address(source_addr, ll.sender); + detect_duplicate_address(source_addr, ll); // step 4: update location table with SO.PV (see C.2) auto& source_entry = m_location_table.update(shb.source_position); assert(source_entry.has_position_vector()); + m_location_table.update(ll.channel, ll.sender, shb.source_position.gn_addr); // step 5: update SO.PDR in location table (see B.2) const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application); - source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); + source_entry.update_pdr(ll.channel, packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); // step 6: set SO LocTE to neighbour source_entry.set_neighbour(true); @@ -965,14 +985,15 @@ bool Router::process_extended(const ExtendedPduConstRefs& pdu, con const Address& source_addr = beacon.source_position.gn_addr; // step 3: execute duplicate address detection (see 9.2.1.5) - detect_duplicate_address(source_addr, ll.sender); + detect_duplicate_address(source_addr, ll); // step 4: update location table with SO.PV (see C.2) auto& source_entry = m_location_table.update(beacon.source_position); + m_location_table.update(ll.channel, ll.sender, beacon.source_position.gn_addr); // step 5: update SO.PDR in location table (see B.2) const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application); - source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); + source_entry.update_pdr(ll.channel, packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); // step 6: set SO LocTE to neighbour source_entry.set_neighbour(true); @@ -1014,12 +1035,12 @@ bool Router::process_extended(const ExtendedPduConstRefs& pd } // step 4: execute DAD - detect_duplicate_address(source_addr, ll.sender); + detect_duplicate_address(source_addr, ll); // step 5 & step 6 (make sure IS_NEIGHBOUR is false for new location table entry) const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application); auto& source_entry = m_location_table.update(gbc.source_position); - source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); + source_entry.update_pdr(ll.channel, packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta); if (!locte_exists) { // step 5b only source_entry.set_neighbour(false); @@ -1037,11 +1058,11 @@ bool Router::process_extended(const ExtendedPduConstRefs& pd return within_destination; // discard packet (step 9a) } else if (m_mib.itsGnMaxPacketDataRate < std::numeric_limits::max()) { // do packet data rate checks (annex B.2) if set maximum rate is not "infinity" (i.e. max unsigned value) - if (source_entry.get_pdr() > m_mib.itsGnMaxPacketDataRate * 1000.0) { + if (source_entry.get_pdr(ll.channel) > m_mib.itsGnMaxPacketDataRate * 1000.0) { forwarding_stopped(ForwardingStopReason::SOURCE_PDR); return within_destination; // omit forwarding, source exceeds PDR limit } else if (const auto* sender_entry = m_location_table.get_entry(ll.sender)) { - if (sender_entry->get_pdr() > m_mib.itsGnMaxPacketDataRate * 1000.0) { + if (sender_entry->get_pdr(ll.channel) > m_mib.itsGnMaxPacketDataRate * 1000.0) { forwarding_stopped(ForwardingStopReason::SENDER_PDR); return within_destination; // omit forwarding, sender exceeds PDR limit } @@ -1056,7 +1077,7 @@ bool Router::process_extended(const ExtendedPduConstRefs& pd using Packet = PendingPacketGbc::Packet; - auto transmit = [this](Packet&& packet, const MacAddress& mac) { + auto transmit = [this, ll](Packet&& packet, const MacAddress& destination) { // step 13: execute media-dependent procedures execute_media_procedures(m_mib.itsGnIfType); @@ -1066,8 +1087,12 @@ bool Router::process_extended(const ExtendedPduConstRefs& pd std::tie(pdu, payload) = std::move(packet); dcc::DataRequest request; - request.destination = mac; - request.source = m_local_position_vector.gn_addr.mid(); + request.destination = destination; + + // TODO: implement channel offloading + // send out on the same interface as received + request.source = m_channel_mac_map.at(ll.channel); + request.dcc_profile = dcc::Profile::DP3; request.ether_type = geonet::ether_type; request.lifetime = std::chrono::seconds(pdu->basic().lifetime.decode() / units::si::seconds); @@ -1088,7 +1113,7 @@ bool Router::process_extended(const ExtendedPduConstRefs& pd // step 10: store & carry forwarding procedure const bool scf = pdu.common().traffic_class.store_carry_forward(); - if (scf && !m_location_table.has_neighbours()) { + if (scf && !m_location_table.has_neighbours(ll.channel)) { PacketBuffer::data_ptr data { new PendingPacketBufferData(std::move(fwd_packet)) }; m_bc_forward_buffer.push(std::move(data), m_runtime.now()); } else { @@ -1110,19 +1135,32 @@ void Router::flush_unicast_forwarding_buffer(const Address& source) m_uc_forward_buffer.flush(m_runtime.now()); } -void Router::detect_duplicate_address(const Address& source, const MacAddress& sender) +void Router::detect_duplicate_address(const Address& source, const LinkLayer& ll) { // EN 302 636-4-1 V1.3.1 10.2.1.5: DAD is only applied for AUTO if (m_mib.itsGnLocalAddrConfMethod == AddrConfMethod::AUTO) { const Address& local = m_local_position_vector.gn_addr; - if (source == local || sender == local.mid()) { + auto mac = m_channel_mac_map.at(ll.channel); + bool is_gn_same = source == local; + bool is_mac_same = ll.sender == mac; + if ( is_gn_same || is_mac_same) { MacAddress random_mac_addr; std::uniform_int_distribution octet_dist; for (auto& octet : random_mac_addr.octets) { octet = octet_dist(m_random_gen); } - - m_local_position_vector.gn_addr.mid(random_mac_addr); + if (is_gn_same) { + m_local_position_vector.gn_addr.mid(random_mac_addr); + // TODO: callback + } + if (is_mac_same) { + auto interface = m_mac_interface_map.at(mac); + m_channel_mac_map.erase(ll.channel); + m_mac_interface_map.erase(mac); + m_channel_mac_map.insert({ll.channel, random_mac_addr}); + m_mac_interface_map.insert({random_mac_addr, interface}); + // TODO: callback to device + } } } } diff --git a/vanetza/geonet/router.hpp b/vanetza/geonet/router.hpp index fb3f9ae3c..ddcefaa2c 100644 --- a/vanetza/geonet/router.hpp +++ b/vanetza/geonet/router.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -77,6 +78,9 @@ class Router using PendingPacketForwarding = PendingPacket; + using AccessInterface = std::tuple; + using AccessInterfaceList = std::vector; + /// Reason for packet drop used by drop hook enum class PacketDropReason { @@ -142,7 +146,7 @@ class Router * \param sender MAC address of sender * \param destination MAC address of destination (might be broadcast) */ - void indicate(UpPacketPtr, const MacAddress& sender, const MacAddress& destination); + void indicate(UpPacketPtr, const MacAddress& sender, const MacAddress& destination, const Channel channel); /** * \brief When a packet is dropped, this Hook is invoked @@ -179,11 +183,11 @@ class Router void set_security_entity(security::SecurityEntity* entity); /** - * \brief Register access layer interface + * \brief Register access layer interfaces * - * \param ifc interface used for passing packets down to access layer + * \param ifc_list interfaces used for passing packets down to access layer */ - void set_access_interface(dcc::RequestInterface* ifc); + void set_access_interfaces(AccessInterfaceList ifc_list); /** * \brief Set Router's own GeoNetworking address @@ -360,11 +364,12 @@ class Router /** * \brief Pass down the packet to the access layer. * + * \param addr MAC address of source * \param addr MAC address of destination * \param pdu header information * \param payload Packet payload */ - void pass_down(const MacAddress&, PduPtr, DownPacketPtr); + void pass_down(const MacAddress&, const MacAddress&, PduPtr, DownPacketPtr); /** * \brief Send packet using the information in the DataRequest. @@ -373,6 +378,7 @@ class Router * \param request containing transmission parameters * \param pdu header information * \param payload Packet payload + * \param request_interface request interface */ void pass_down(const dcc::DataRequest&, PduPtr, DownPacketPtr); @@ -393,7 +399,7 @@ class Router * \param source address of source (from packet header) * \param sender address of sender (link layer) */ - void detect_duplicate_address(const Address& source, const MacAddress& sender); + void detect_duplicate_address(const Address& source, const LinkLayer& ll); /** * \brief Detect duplicate packets @@ -413,7 +419,7 @@ class Router * \param payload * \return next hop */ - NextHop greedy_forwarding(PendingPacketForwarding&&); + NextHop greedy_forwarding(PendingPacketForwarding&&, const LinkLayer* ll); /** * \brief Determine next hop for non-area contention-based forwarding @@ -424,7 +430,7 @@ class Router * \param sender optional sender MAC address (if not first hop) * \return next hop */ - NextHop non_area_contention_based_forwarding(PendingPacketForwarding&&, const MacAddress* sender); + NextHop non_area_contention_based_forwarding(PendingPacketForwarding&&, const MacAddress* sender, Channel channel); /** * \brief Determine next hop for area contention-based forwarding @@ -513,7 +519,10 @@ class Router const MIB& m_mib; Runtime& m_runtime; - dcc::RequestInterface* m_request_interface; + + std::map m_channel_mac_map; + std::map m_mac_interface_map; + security::SecurityEntity* m_security_entity; transport_map_t m_transport_ifcs; LocationTable m_location_table;