1#include <vanetza/btp/data_indication.hpp>
2#include <vanetza/btp/data_request.hpp>
3#include <vanetza/common/its_aid.hpp>
4#include <vanetza/common/position_fix.hpp>
5#include <vanetza/common/runtime.hpp>
6#include <vanetza/dcc/data_request.hpp>
7#include <vanetza/dcc/interface.hpp>
8#include <vanetza/dcc/profile.hpp>
9#include <vanetza/net/mac_address.hpp>
10#include <vanetza/net/osi_layer.hpp>
11#include <vanetza/units/frequency.hpp>
12#include <vanetza/units/length.hpp>
13#include <vanetza/units/time.hpp>
14#include <vanetza/geonet/router.hpp>
15#include <vanetza/geonet/cbf_counter.hpp>
16#include <vanetza/geonet/data_confirm.hpp>
17#include <vanetza/geonet/dcc_field_generator.hpp>
18#include <vanetza/geonet/duplicate_packet_list.hpp>
19#include <vanetza/geonet/indication_context.hpp>
20#include <vanetza/geonet/loctex_g5.hpp>
21#include <vanetza/geonet/next_hop.hpp>
22#include <vanetza/geonet/pdu_conversion.hpp>
23#include <vanetza/geonet/repetition_dispatcher.hpp>
24#include <vanetza/geonet/transport_interface.hpp>
25#include <vanetza/geonet/extended_pdu.hpp>
26#include <vanetza/geonet/secured_pdu.hpp>
27#include <boost/units/cmath.hpp>
42 ControlInfo(
const DataRequest request) :
43 communication_profile(request.communication_profile),
44 its_aid(request.its_aid) {}
46 const CommunicationProfile communication_profile;
51class PendingPacketBufferData :
public packet_buffer::Data
54 PendingPacketBufferData(PendingPacket<PDU>&& packet) : m_packet(
std::move(packet)) {}
56 std::size_t length()
const override
58 return m_packet.length();
61 Clock::duration reduce_lifetime(Clock::duration d)
override
63 return m_packet.reduce_lifetime(d);
72 PendingPacket<PDU> m_packet;
75dcc::RequestInterface* get_default_request_interface()
77 static dcc::NullRequestInterface null;
81DccFieldGenerator* get_default_dcc_field_generator()
83 static NullDccFieldGenerator null;
88auto create_forwarding_duplicate(
const PDU& pdu,
const UpPacket& packet) ->
89std::tuple<std::unique_ptr<ExtendedPdu<typename PDU::ExtendedHeader>>, std::unique_ptr<DownPacket>>
91 using pdu_type = ExtendedPdu<typename PDU::ExtendedHeader>;
92 std::unique_ptr<pdu_type> pdu_dup {
new pdu_type { pdu }};
93 std::unique_ptr<DownPacket> packet_dup;
95 packet_dup.reset(
new DownPacket());
97 packet_dup = duplicate(packet);
99 return std::make_tuple(std::move(pdu_dup), std::move(packet_dup));
102template<
typename PDU>
103PDU& get_pdu(
const std::tuple<std::unique_ptr<PDU>, std::unique_ptr<DownPacket>>& packet)
105 PDU* pdu = std::get<0>(packet).get();
110std::unique_ptr<CbfCounter> create_cbf_counter(Runtime& rt,
const MIB& mib)
112 std::unique_ptr<CbfCounter> counter;
113 if (mib.vanetzaFadingCbfCounter) {
114 counter.reset(
new CbfCounterFading(rt, units::clock_cast(mib.vanetzaFadingCbfCounterLifetime)));
116 counter.reset(
new CbfCounterContending());
124using units::clock_cast;
125using PendingPacketGbc = PendingPacket<GbcPdu>;
127const access::EtherType ether_type = access::ethertype::GeoNetworking;
129Router::Router(Runtime& rt,
const MIB& mib) :
132 m_request_interface(get_default_request_interface()),
133 m_dcc_field_generator(get_default_dcc_field_generator()),
134 m_security_entity(nullptr),
135 m_location_table(mib, m_runtime),
136 m_bc_forward_buffer(mib.itsGnBcForwardingPacketBufferSize * 1024),
137 m_uc_forward_buffer(mib.itsGnUcForwardingPacketBufferSize * 1024),
138 m_cbf_buffer(m_runtime,
139 [](PendingPacketGbc&& packet) { packet.process(); },
140 create_cbf_counter(rt, mib),
141 mib.itsGnCbfPacketBufferSize * 1024),
142 m_local_sequence_number(0),
143 m_repeater(m_runtime,
144 std::bind(&Router::dispatch_repetition,
this, std::placeholders::_1, std::placeholders::_2)),
145 m_random_gen(mib.vanetzaDefaultSeed)
147 if (!m_mib.vanetzaDisableBeaconing) {
148 if (!m_mib.vanetzaDeferInitialBeacon) {
150 reset_beacon_timer(Clock::duration::zero());
153 std::uniform_real_distribution<double> dist(0.0, 1.0);
154 const auto first_beacon = dist(m_random_gen) * m_mib.itsGnBeaconServiceRetransmitTimer;
155 reset_beacon_timer(clock_cast(first_beacon));
159 m_gbc_memory.capacity(m_mib.vanetzaGbcMemoryCapacity);
164 m_runtime.cancel(
this);
172 m_local_position_vector.timestamp = m_runtime.now();
173 m_local_position_vector.latitude =
static_cast<geo_angle_i32t
>(position_fix.latitude);
174 m_local_position_vector.longitude =
static_cast<geo_angle_i32t
>(position_fix.longitude);
175 if (m_mib.itsGnIsMobile) {
176 m_local_position_vector.speed =
static_cast<LongPositionVector::speed_u15t
>(position_fix.speed.value());
177 m_local_position_vector.heading =
static_cast<heading_u16t
>(position_fix.course.value() - units::TrueNorth::from_value(0.0));
179 m_local_position_vector.speed =
static_cast<LongPositionVector::speed_u15t
>(0);
180 m_local_position_vector.heading =
static_cast<heading_u16t
>(0);
183 m_local_position_vector.position_accuracy_indicator =
184 position_fix.confidence.semi_major * 2.0 < m_mib.itsGnPaiInterval;
189 m_transport_ifcs[proto] = ifc;
194 m_security_entity = entity;
199 m_request_interface = (ifc ==
nullptr ? get_default_request_interface() : ifc);
200 assert(m_request_interface !=
nullptr);
205 m_dcc_field_generator = (dcc ==
nullptr) ? get_default_dcc_field_generator() : dcc;
206 assert(m_dcc_field_generator !=
nullptr);
211 m_local_position_vector.gn_addr = addr;
214void Router::set_random_seed(std::uint_fast32_t seed)
216 m_random_gen.seed(seed);
222 result ^= validate_data_request(request, m_mib);
223 result ^= validate_payload(payload, m_mib);
225 if (result.accepted()) {
229 if (request.repetition) {
231 m_repeater.add(request, *payload);
235 auto pdu = create_shb_pdu(request);
236 pdu->common().payload = payload->size();
238 ControlInfo ctrl(request);
239 auto transmit = [
this, ctrl](PendingPacket::Packet&& packet) {
240 std::unique_ptr<ShbPdu> pdu;
241 std::unique_ptr<DownPacket> payload;
242 std::tie(pdu, payload) = std::move(packet);
245 pdu->extended().source_position = m_local_position_vector;
248 if (m_mib.itsGnSecurity) {
249 payload = encap_packet(ctrl.its_aid, *pdu, std::move(payload));
253 execute_media_procedures(ctrl.communication_profile);
256 pass_down(cBroadcastMacAddress, std::move(pdu), std::move(payload));
259 reset_beacon_timer();
262 PendingPacket packet(std::make_tuple(std::move(pdu), std::move(payload)), transmit);
265 if (request.traffic_class.store_carry_forward() && !m_location_table.has_neighbours()) {
266 PacketBuffer::data_ptr data {
new PendingPacketBufferData<ShbPdu>(std::move(packet)) };
267 m_bc_forward_buffer.push(std::move(data), m_runtime.now());
280 result ^= validate_data_request(request, m_mib);
281 result ^= validate_payload(payload, m_mib);
283 if (!result.accepted())
291 if (request.repetition) {
292 m_repeater.add(request, *payload);
296 using Packet = PendingPacket::Packet;
299 auto pdu = create_gbc_pdu(request);
300 pdu->common().payload = payload->size();
302 ControlInfo ctrl(request);
303 auto transmit = [
this, ctrl](Packet&& packet,
const MacAddress& mac) {
304 std::unique_ptr<GbcPdu> pdu;
305 std::unique_ptr<DownPacket> payload;
306 std::tie(pdu, payload) = std::move(packet);
309 pdu->extended().source_position = m_local_position_vector;
312 if (m_mib.itsGnSecurity) {
313 assert(pdu->basic().next_header == NextHeaderBasic::Secured);
314 payload = encap_packet(ctrl.its_aid, *pdu, std::move(payload));
320 execute_media_procedures(ctrl.communication_profile);
323 pass_down(mac, std::move(pdu), std::move(payload));
326 auto forwarding = [
this, transmit](Packet&& packet) {
331 std::move(nh).process();
334 PendingPacket packet(std::make_tuple(std::move(pdu), std::move(payload)), forwarding);
337 const bool scf = request.traffic_class.store_carry_forward();
338 if (scf && !m_location_table.has_neighbours()) {
339 PacketBuffer::data_ptr data {
new PendingPacketBufferData<GbcPdu>(std::move(packet)) };
340 m_bc_forward_buffer.push(std::move(data), m_runtime.now());
350 return DataConfirm(DataConfirm::ResultCode::Rejected_Unspecified);
353DataConfirm Router::request(
const GucDataRequest&, DownPacketPtr)
355 return DataConfirm(DataConfirm::ResultCode::Rejected_Unspecified);
358DataConfirm Router::request(
const TsbDataRequest&, DownPacketPtr)
360 return DataConfirm(DataConfirm::ResultCode::Rejected_Unspecified);
367 struct indication_visitor :
public boost::static_visitor<>
370 m_router(router), m_link_layer(link_layer), m_packet(std::move(packet))
377 m_router.indicate_basic(ctx);
383 m_router.indicate_basic(ctx);
388 UpPacketPtr m_packet;
392 link_layer.sender = sender;
393 link_layer.destination = destination;
395 UpPacket* packet_ptr = packet.get();
396 indication_visitor visitor(*
this, link_layer, std::move(packet));
397 boost::apply_visitor(visitor, *packet_ptr);
404 packet_dropped(PacketDropReason::Parse_Basic_Header);
405 }
else if (basic->version.raw() != m_mib.itsGnProtocolVersion) {
406 packet_dropped(PacketDropReason::ITS_Protocol_Version);
409 indication.remaining_packet_lifetime = basic->lifetime;
410 indication.remaining_hop_limit = basic->hop_limit;
412 if (basic->next_header == NextHeaderBasic::Secured) {
413 indication.security_report = security::DecapReport::Incompatible_Protocol;
414 indicate_secured(ctx, *basic);
415 }
else if (basic->next_header == NextHeaderBasic::Common) {
416 if (!m_mib.itsGnSecurity || SecurityDecapHandling::Non_Strict == m_mib.itsGnSnDecapResultHandling) {
417 indication.security_report = security::DecapReport::Unsigned_Message,
418 indicate_common(ctx, *basic);
420 packet_dropped(PacketDropReason::Decap_Unsuccessful_Strict);
430 packet_dropped(PacketDropReason::Parse_Common_Header);
431 }
else if (common->maximum_hop_limit < basic.hop_limit) {
433 packet_dropped(PacketDropReason::Hop_Limit);
436 indication.traffic_class = common->traffic_class;
437 switch (common->next_header)
439 case NextHeaderCommon::BTP_A:
440 indication.upper_protocol = UpperProtocol::BTP_A;
442 case NextHeaderCommon::BTP_B:
443 indication.upper_protocol = UpperProtocol::BTP_B;
445 case NextHeaderCommon::IPv6:
446 indication.upper_protocol = UpperProtocol::IPv6;
449 indication.upper_protocol = UpperProtocol::Unknown;
454 m_location_table.drop_expired();
457 flush_broadcast_forwarding_buffer();
460 indicate_extended(ctx, *common);
471 struct secured_payload_visitor :
public boost::static_visitor<>
474 m_router(router), m_context(ctx), m_basic(basic)
481 m_router.indicate_common(ctx, m_basic);
487 m_router.indicate_common(ctx, m_basic);
495 auto secured_message = ctx.parse_secured();
496 if (!secured_message) {
497 packet_dropped(PacketDropReason::Parse_Secured_Header);
498 }
else if (m_security_entity) {
500 using namespace vanetza::security;
502 ctx.service_primitive().security_report = decap_confirm.report;
503 ctx.service_primitive().its_aid = decap_confirm.its_aid;
504 ctx.service_primitive().permissions = decap_confirm.permissions;
505 secured_payload_visitor visitor(*
this, ctx, basic);
508 if (DecapReport::Success == decap_confirm.report) {
509 boost::apply_visitor(visitor, decap_confirm.plaintext_payload);
510 }
else if (SecurityDecapHandling::Non_Strict == m_mib.itsGnSnDecapResultHandling) {
513 switch (decap_confirm.report) {
514 case DecapReport::False_Signature:
515 case DecapReport::Invalid_Certificate:
516 case DecapReport::Revoked_Certificate:
517 case DecapReport::Inconsistant_Chain:
518 case DecapReport::Invalid_Timestamp:
519 case DecapReport::Invalid_Mobility_Data:
520 case DecapReport::Unsigned_Message:
521 case DecapReport::Signer_Certificate_Not_Found:
522 case DecapReport::Unsupported_Signer_Identifier_Type:
523 case DecapReport::Unencrypted_Message:
525 boost::apply_visitor(visitor, decap_confirm.plaintext_payload);
527 case DecapReport::Duplicate_Message:
528 case DecapReport::Incompatible_Protocol:
529 case DecapReport::Decryption_Error:
531 packet_dropped(PacketDropReason::Decap_Unsuccessful_Non_Strict);
536 packet_dropped(PacketDropReason::Decap_Unsuccessful_Strict);
539 packet_dropped(PacketDropReason::Security_Entity_Missing);
545 struct extended_header_visitor :
public boost::static_visitor<bool>
548 m_router(router), m_context(ctx), m_packet(packet)
555 indication.transport_type = TransportType::SHB;
558 auto& pdu = m_context.pdu();
561 return m_router.process_extended(shb_pdu, m_packet, m_context.link_layer());
567 indication.transport_type = TransportType::GBC;
569 indication.destination = gbc.destination(m_context.pdu().common().header_type);
571 auto& pdu = m_context.pdu();
573 return m_router.process_extended(gbc_pdu, m_packet, m_context.link_layer());
578 auto& pdu = m_context.pdu();
580 return m_router.process_extended(beacon_pdu, m_packet, m_context.link_layer());
585 const UpPacket& m_packet;
588 auto extended = ctx.parse_extended(common.header_type);
589 UpPacketPtr packet = ctx.
finish();
593 packet_dropped(PacketDropReason::Parse_Extended_Header);
594 }
else if (common.payload != size(*packet, OsiLayer::Transport, max_osi_layer())) {
595 packet_dropped(PacketDropReason::Payload_Size);
597 extended_header_visitor visitor(*
this, ctx, *packet);
598 if (boost::apply_visitor(visitor, *extended)) {
599 pass_up(ctx.service_primitive(), std::move(packet));
607 const Area& destination = packet.pdu().extended().destination(packet.pdu().common().header_type);
608 if (inside_or_at_border(destination, m_local_position_vector.position())) {
609 switch (m_mib.itsGnAreaForwardingAlgorithm) {
610 case BroadcastForwarding::Unspecified:
612 case BroadcastForwarding::SIMPLE:
614 nh.
transmit(std::move(packet), cBroadcastMacAddress);
616 case BroadcastForwarding::CBF:
617 nh = area_contention_based_forwarding(std::move(packet), ll ? &ll->sender :
nullptr);
619 case BroadcastForwarding::Advanced:
620 nh = area_advanced_forwarding(std::move(packet), ll);
623 throw std::runtime_error(
"unhandled area forwarding algorithm");
628 const LongPositionVector* pv_se = ll ? m_location_table.get_position(ll->sender) :
nullptr;
629 if (pv_se && pv_se->position_accuracy_indicator && inside_or_at_border(destination, pv_se->position())) {
631 forwarding_stopped(ForwardingStopReason::Outside_Destination_Area);
633 switch (m_mib.itsGnNonAreaForwardingAlgorithm) {
634 case UnicastForwarding::Unspecified:
636 case UnicastForwarding::Greedy:
637 nh = greedy_forwarding(std::move(packet));
639 case UnicastForwarding::CBF:
640 nh = non_area_contention_based_forwarding(std::move(packet), ll ? &ll->sender :
nullptr);
643 throw std::runtime_error(
"unhandled non-area forwarding algorithm");
652void Router::execute_media_procedures(CommunicationProfile com_profile)
654 switch (com_profile) {
655 case CommunicationProfile::ITS_G5:
656 execute_itsg5_procedures();
658 case CommunicationProfile::Unspecified:
662 throw std::runtime_error(
"Unhandled communication profile");
667void Router::execute_itsg5_procedures()
676 if (pdu->secured()) {
677 if (pdu->basic().next_header != NextHeaderBasic::Secured) {
678 throw std::runtime_error(
"PDU with secured message but Secured not set in basic header");
680 if (payload->size(OsiLayer::Transport, max_osi_layer()) > 0) {
681 throw std::runtime_error(
"PDU with secured message and illegal upper layer payload");
684 if (pdu->basic().next_header == NextHeaderBasic::Secured) {
685 throw std::runtime_error(
"PDU without secured message but Secured set in basic header");
690 assert(m_request_interface);
691 m_request_interface->request(request, std::move(payload));
694void Router::pass_down(
const MacAddress& addr, PduPtr pdu, DownPacketPtr payload)
699 request.destination = addr;
700 request.source = m_local_position_vector.gn_addr.mid();
701 request.dcc_profile = map_tc_onto_profile(pdu->common().traffic_class);
702 request.ether_type = geonet::ether_type;
703 request.lifetime = clock_cast(pdu->basic().lifetime.decode());
705 pass_down(request, std::move(pdu), std::move(payload));
711 if (transport !=
nullptr) {
712 transport->indicate(ind, std::move(packet));
716void Router::on_beacon_timer_expired()
718 if (m_mib.vanetzaDisableBeaconing) {
725 auto pdu = create_beacon_pdu();
727 if (m_mib.itsGnSecurity) {
728 pdu->basic().next_header = NextHeaderBasic::Secured;
729 payload = encap_packet(aid::GN_MGMT, *pdu, std::move(payload));
731 pdu->basic().next_header = NextHeaderBasic::Common;
734 execute_media_procedures(m_mib.itsGnIfType);
735 pass_down(cBroadcastMacAddress, std::move(pdu), std::move(payload));
736 reset_beacon_timer();
739void Router::reset_beacon_timer()
741 using duration_t =
decltype(m_mib.itsGnBeaconServiceRetransmitTimer);
742 using real_t = duration_t::value_type;
743 static_assert(std::is_floating_point<real_t>::value,
"floating point type expected");
745 std::uniform_real_distribution<real_t> dist_jitter(0.0, 1.0);
746 const auto jitter = dist_jitter(m_random_gen);
747 const duration_t next_beacon = m_mib.itsGnBeaconServiceRetransmitTimer +
748 jitter * m_mib.itsGnBeaconServiceMaxJitter;
749 reset_beacon_timer(clock_cast(next_beacon));
752void Router::reset_beacon_timer(Clock::duration next_beacon)
754 m_runtime.cancel(
this);
755 m_runtime.schedule(next_beacon, [
this](Clock::time_point) {
756 on_beacon_timer_expired();
760void Router::dispatch_repetition(
const DataRequestVariant& request, std::unique_ptr<DownPacket> payload)
763 boost::apply_visitor(dispatcher, request);
770 const units::Length own = distance(dest, m_local_position_vector.position());
771 units::Length mfr_dist = own;
775 if (neighbour.has_position_vector()) {
776 const units::Length dist = distance(dest, neighbour.get_position_vector().position());
777 if (dist < mfr_dist) {
778 mfr_addr = neighbour.link_layer_address();
784 if (mfr_dist < own) {
785 nh.
transmit(std::move(packet), mfr_addr);
787 const bool scf = packet.pdu().common().traffic_class.store_carry_forward();
790 NextHop nh = greedy_forwarding(std::move(packet));
791 std::move(nh).process();
794 PacketBuffer::data_ptr data {
new PendingPacketBufferData<GbcPdu>(std::move(greedy_packet)) };
795 m_bc_forward_buffer.push(std::move(data), m_runtime.now());
798 nh.
transmit(std::move(packet), cBroadcastMacAddress);
809 const auto cbf_id = identifier(gbc.source_position.gn_addr, gbc.sequence_number);
813 nh.
transmit(std::move(packet), cBroadcastMacAddress);
814 }
else if (m_cbf_buffer.remove(cbf_id)) {
818 const HeaderType ht = packet.pdu().common().header_type;
819 const Area destination = gbc.destination(ht);
820 const auto& epv = m_local_position_vector;
821 const LongPositionVector* pv_se = sender ? m_location_table.get_position(*sender) :
nullptr;
823 if (pv_se && pv_se->position_accuracy_indicator) {
824 const auto& pv_p = destination.position;
825 const units::Length dist_sender = distance(pv_p, pv_se->position());
826 const units::Length dist_local = distance(pv_p, epv.position());
827 if (dist_sender > dist_local) {
828 CbfPacket cbf { std::move(packet), *sender };
829 const auto progress = dist_sender - dist_local;
830 m_cbf_buffer.add(std::move(cbf), clock_cast(timeout_cbf(progress)));
837 CbfPacket cbf { std::move(packet), *sender };
838 const auto to_cbf_max = m_mib.itsGnCbfMaxTime;
839 m_cbf_buffer.add(std::move(cbf), clock_cast(to_cbf_max));
850 const auto cbf_id = identifier(gbc.source_position.gn_addr, gbc.sequence_number);
853 nh.
transmit(std::move(packet), cBroadcastMacAddress);
854 }
else if (m_cbf_buffer.remove(cbf_id) || m_cbf_buffer.counter(cbf_id) >= m_mib.vanetzaCbfMaxCounter) {
857 const units::Duration timeout = timeout_cbf(*sender);
858 m_cbf_buffer.add(
CbfPacket { std::move(packet), *sender }, clock_cast(timeout));
864units::Duration Router::timeout_cbf(units::Length prog)
const
867 const auto dist_max = m_mib.itsGnDefaultMaxCommunicationRange;
868 const auto to_cbf_min = m_mib.itsGnCbfMinTime;
869 const auto to_cbf_max = m_mib.itsGnCbfMaxTime;
871 if (prog > dist_max) {
873 }
else if (prog > 0.0 * units::si::meter) {
874 return to_cbf_max + (to_cbf_min - to_cbf_max) / dist_max * prog;
880units::Duration Router::timeout_cbf(
const MacAddress& sender)
const
883 units::Duration timeout = m_mib.itsGnCbfMaxTime;
885 if (pv_se && pv_se->position_accuracy_indicator) {
886 units::Length dist = distance(pv_se->position(), m_local_position_vector.position());
887 timeout = timeout_cbf(dist);
897 nh.
transmit(std::move(packet), cBroadcastMacAddress);
900 const HeaderType ht = packet.pdu().common().header_type;
901 const Area destination_area = gbc.destination(ht);
902 const std::size_t max_counter = m_mib.vanetzaCbfMaxCounter;
903 const auto cbf_id = identifier(gbc.source_position.gn_addr, gbc.sequence_number);
904 const CbfPacket* cbf_packet = m_cbf_buffer.find(cbf_id);
908 if (m_cbf_buffer.counter(cbf_id) >= max_counter) {
910 m_cbf_buffer.remove(cbf_id);
912 }
else if (!outside_sectorial_contention_area(cbf_packet->
sender(), ll->sender)) {
916 m_cbf_buffer.remove(cbf_id);
919 m_cbf_buffer.update(cbf_id, clock_cast(timeout_cbf(ll->sender)));
923 if (ll->destination == m_local_position_vector.gn_addr.mid()) {
925 nh = greedy_forwarding(packet.duplicate());
927 if (nh.
valid() && nh.
mac() == cBroadcastMacAddress) {
929 static const PendingPacketForwarding::Function noop_fn =
930 [](PendingPacketForwarding::Packet&&,
const MacAddress&) {};
932 CbfPacket cbf { std::move(noop), ll->sender };
933 m_cbf_buffer.add(std::move(cbf), clock_cast(m_mib.itsGnCbfMaxTime));
936 CbfPacket cbf { std::move(packet), ll->sender };
937 m_cbf_buffer.add(std::move(cbf), clock_cast(m_mib.itsGnCbfMaxTime));
943 CbfPacket cbf { std::move(packet), ll->sender };
944 m_cbf_buffer.add(std::move(cbf), clock_cast(timeout_cbf(ll->sender)));
954 using units::si::meter;
955 auto position_sender = m_location_table.get_position(sender);
956 auto position_forwarder = m_location_table.get_position(forwarder);
960 if (position_sender && position_forwarder) {
961 auto dist_r = distance(position_sender->position(), m_local_position_vector.position());
962 auto dist_f = distance(position_forwarder->position(), position_sender->position());
963 const auto dist_max = m_mib.itsGnDefaultMaxCommunicationRange;
965 auto dist_rf = distance(position_forwarder->position(), m_local_position_vector.position());
966 auto angle_fsr = 0.0 * units::si::radians;
967 if (dist_r > 0.0 * meter && dist_f > 0.0 * meter) {
968 auto cos_fsr = (dist_rf * dist_rf - dist_r * dist_r - dist_f * dist_f) /
969 (-2.0 * dist_r * dist_f);
970 angle_fsr = boost::units::acos(cos_fsr);
972 const auto angle_th = m_mib.itsGnBroadcastCBFDefSectorAngle;
974 return !(dist_r < dist_f && dist_f < dist_max && angle_fsr < angle_th);
983 const Address& source_addr = shb.source_position.gn_addr;
986 detect_duplicate_address(source_addr, ll.sender);
989 auto& source_entry = m_location_table.update(shb.source_position);
991 assert(source_entry.has_position_vector() || !is_valid(shb.source_position));
994 const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application);
995 source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta);
998 source_entry.set_neighbour(
true, m_mib.vanetzaNeighbourFlagExpiry);
1001 if (m_mib.itsGnIfType == InterfaceType::ITS_G5) {
1002 boost::optional<DccMcoField> dcc_mco = get_dcc_mco(shb.dcc);
1004 auto& loctex = source_entry.extensions.get<
LocTEX_G5>();
1005 loctex.local_update = m_runtime.now();
1006 loctex.source_update = shb.source_position.timestamp;
1007 loctex.dcc_mco = *dcc_mco;
1018 const Address& source_addr = beacon.source_position.gn_addr;
1021 detect_duplicate_address(source_addr, ll.sender);
1024 auto& source_entry = m_location_table.update(beacon.source_position);
1027 const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application);
1028 source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta);
1031 source_entry.set_neighbour(
true, m_mib.vanetzaNeighbourFlagExpiry);
1041 const Address& source_addr = gbc.source_position.gn_addr;
1042 const Area dest_area = gbc.destination(pdu.common().header_type);
1045 const bool locte_exists = m_location_table.has_entry(source_addr);
1048 const bool within_destination = inside_or_at_border(dest_area, m_local_position_vector.position());
1050 bool duplicate_packet =
false;
1051 if (!within_destination) {
1052 if (m_mib.itsGnNonAreaForwardingAlgorithm == UnicastForwarding::Unspecified ||
1053 m_mib.itsGnNonAreaForwardingAlgorithm == UnicastForwarding::Greedy) {
1054 duplicate_packet = detect_duplicate_packet(source_addr, gbc.sequence_number);
1058 if (m_mib.itsGnAreaForwardingAlgorithm == BroadcastForwarding::Unspecified ||
1059 m_mib.itsGnAreaForwardingAlgorithm == BroadcastForwarding::SIMPLE) {
1060 duplicate_packet = detect_duplicate_packet(source_addr, gbc.sequence_number);
1064 if (duplicate_packet) {
1070 if (m_mib.vanetzaMultiHopDuplicateAddressDetection) {
1072 detect_duplicate_address(source_addr, ll.sender);
1076 const std::size_t packet_size = size(packet, OsiLayer::Network, OsiLayer::Application);
1077 auto& source_entry = m_location_table.update(gbc.source_position);
1078 source_entry.update_pdr(packet_size, m_mib.itsGnMaxPacketDataRateEmaBeta);
1079 if (!locte_exists) {
1081 source_entry.set_neighbour(
false);
1088 flush_unicast_forwarding_buffer(source_addr);
1091 if (pdu.basic().hop_limit <= 1) {
1092 forwarding_stopped(ForwardingStopReason::Hop_Limit);
1093 return decide_pass_up(within_destination, gbc);
1094 }
else if (m_mib.itsGnMaxPacketDataRate < std::numeric_limits<
decltype(m_mib.itsGnMaxPacketDataRate)>::max()) {
1096 if (source_entry.get_pdr() > m_mib.itsGnMaxPacketDataRate * 1000.0) {
1097 forwarding_stopped(ForwardingStopReason::Source_PDR);
1098 return decide_pass_up(within_destination, gbc);
1099 }
else if (
const auto* sender_entry = m_location_table.get_entry(ll.sender)) {
1100 if (sender_entry->get_pdr() > m_mib.itsGnMaxPacketDataRate * 1000.0) {
1101 forwarding_stopped(ForwardingStopReason::Sender_PDR);
1102 return decide_pass_up(within_destination, gbc);
1108 auto fwd_dup = create_forwarding_duplicate(pdu, packet);
1109 GbcPdu& fwd_pdu = get_pdu(fwd_dup);
1110 --fwd_pdu.basic().hop_limit;
1111 assert(fwd_pdu.basic().hop_limit + 1 == pdu.basic().hop_limit);
1113 using Packet = PendingPacketGbc::Packet;
1115 auto transmit = [
this](Packet&& packet,
const MacAddress& mac) {
1117 execute_media_procedures(m_mib.itsGnIfType);
1120 std::unique_ptr<Pdu> pdu;
1121 std::unique_ptr<DownPacket> payload;
1122 std::tie(pdu, payload) = std::move(packet);
1125 request.destination = mac;
1126 request.source = m_local_position_vector.gn_addr.mid();
1127 request.dcc_profile = dcc::Profile::DP3;
1128 request.ether_type = geonet::ether_type;
1129 request.lifetime = clock_cast(pdu->basic().lifetime.decode());
1131 pass_down(request, std::move(pdu), std::move(payload));
1134 auto forwarding = [
this, transmit, ll](Packet&& packet) {
1137 NextHop forwarding = forwarding_algorithm_selection(std::move(tmp), &ll);
1140 std::move(forwarding).process();
1146 const bool scf = pdu.common().traffic_class.store_carry_forward();
1147 if (scf && !m_location_table.has_neighbours()) {
1148 PacketBuffer::data_ptr data {
new PendingPacketBufferData<GbcPdu>(std::move(fwd_packet)) };
1149 m_bc_forward_buffer.push(std::move(data), m_runtime.now());
1151 fwd_packet.process();
1155 return decide_pass_up(within_destination, gbc);
1160 if (m_mib.vanetzaGbcMemoryCapacity == 0) {
1162 return within_destination;
1163 }
else if (within_destination) {
1165 return !m_gbc_memory.remember(std::make_tuple(gbc.source_position.gn_addr, gbc.sequence_number));
1171void Router::flush_broadcast_forwarding_buffer()
1173 m_bc_forward_buffer.flush(m_runtime.now());
1176void Router::flush_unicast_forwarding_buffer(
const Address& source)
1179 m_uc_forward_buffer.flush(m_runtime.now());
1185 if (m_mib.itsGnLocalAddrConfMethod == AddrConfMethod::Auto) {
1186 const Address& local = m_local_position_vector.gn_addr;
1187 if (source == local || sender == local.mid()) {
1189 std::uniform_int_distribution<unsigned> octet_dist;
1190 for (
auto& octet : random_mac_addr.octets) {
1191 octet = octet_dist(m_random_gen);
1194 m_local_position_vector.gn_addr.mid(random_mac_addr);
1201 bool is_duplicate =
false;
1202 ObjectContainer& so_ext = m_location_table.get_or_create_entry(addr_so).extensions;
1205 is_duplicate = dpl->
check(sn);
1207 std::unique_ptr<DuplicatePacketList> dpl {
new DuplicatePacketList(m_mib.itsGnDPLLength) };
1208 is_duplicate = dpl->
check(sn);
1209 so_ext.insert(std::move(dpl));
1211 return is_duplicate;
1216 std::unique_ptr<ShbPdu> pdu {
new ShbPdu(request, m_mib) };
1217 pdu->basic().hop_limit = 1;
1218 pdu->common().header_type = HeaderType::TSB_Single_Hop;
1219 pdu->common().maximum_hop_limit = 1;
1220 pdu->extended().source_position = m_local_position_vector;
1221 pdu->extended().dcc = m_dcc_field_generator->generate_dcc_field();
1225std::unique_ptr<BeaconPdu> Router::create_beacon_pdu()
1227 std::unique_ptr<BeaconPdu> pdu {
new BeaconPdu(m_mib) };
1228 pdu->basic().hop_limit = 1;
1229 pdu->common().next_header = NextHeaderCommon::Any;
1230 pdu->common().header_type = HeaderType::Beacon;
1231 pdu->common().maximum_hop_limit = 1;
1233 pdu->extended().source_position = m_local_position_vector;
1239 std::unique_ptr<GbcPdu> pdu {
new GbcPdu(request, m_mib) };
1240 pdu->common().header_type = gbc_header_type(request.destination);
1241 pdu->extended().sequence_number = m_local_sequence_number++;
1242 pdu->extended().source_position = m_local_position_vector;
1243 pdu->extended().destination(request.destination);
1247Router::DownPacketPtr Router::encap_packet(ItsAid its_aid,
Pdu& pdu, DownPacketPtr packet)
1252 sec_payload[OsiLayer::Network] =
SecuredPdu(pdu);
1253 sec_payload.
merge(*packet, OsiLayer::Transport, max_osi_layer());
1254 encap_request.plaintext_payload = std::move(sec_payload);
1255 encap_request.its_aid = its_aid;
1257 if (m_security_entity) {
1259 pdu.secured(std::move(confirm.sec_packet));
1261 throw std::runtime_error(
"security entity unavailable");
1264 assert(size(*packet, OsiLayer::Transport, max_osi_layer()) == 0);
1265 assert(pdu.basic().next_header == NextHeaderBasic::Secured);
1271 std::string reason_string;
1275 case Router::PacketDropReason::Parse_Basic_Header:
1276 reason_string =
"Parse_Basic_Header";
1278 case Router::PacketDropReason::Parse_Common_Header:
1279 reason_string =
"Parse_Common_Header";
1281 case Router::PacketDropReason::Parse_Secured_Header:
1282 reason_string =
"Parse_Secured_Header";
1284 case Router::PacketDropReason::Parse_Extended_Header:
1285 reason_string =
"Parse_Extended_Header";
1287 case Router::PacketDropReason::ITS_Protocol_Version:
1288 reason_string =
"ITS_Protocol_Version";
1290 case Router::PacketDropReason::Decap_Unsuccessful_Non_Strict:
1291 reason_string =
"Decap_Unsuccessful_Non_Strict";
1293 case Router::PacketDropReason::Decap_Unsuccessful_Strict:
1294 reason_string =
"Decap_Unsuccessful_Strict";
1296 case Router::PacketDropReason::Hop_Limit:
1297 reason_string =
"Hop_Limit";
1299 case Router::PacketDropReason::Payload_Size:
1300 reason_string =
"Payload_Size";
1302 case Router::PacketDropReason::Security_Entity_Missing:
1303 reason_string =
"Security_Entity_Missing";
1306 reason_string =
"UNKNOWN";
1310 return reason_string;
ChunckPacket is a packet consisting of several memory chunks.
ChunkPacket & merge(ChunkPacket &packet, OsiLayer from, OsiLayer to)
const MacAddress & sender() const
bool check(SequenceNumber)
virtual UpPacketPtr finish()=0
const MacAddress & mac() const
void transmit(Packet &&packet, const MacAddress &destination)
PacketDropReason
Reason for packet drop used by drop hook.
contains output of the verify process described in TS 102 723-8 v1.0.0 (2013-07) TS 102 636-4-1 v1....
contains input for verify process described in TS 102 723-8 v1.0.0 (2013-07) TS 102 636-4-1 v1....
contains output of the signing process described in TS 102 636-4-1 v1.2.3 (2015-01)