blob: dcfc2d851f419b0880abc3cb68eefea06be1d6e8 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cinttypes>
bnc463f2352019-10-10 04:49:34 -07006#include <utility>
QUICHE teama6ef0a62019-03-07 20:34:33 -05007
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
QUICHE team6dcf6ab2019-12-11 10:10:51 -08009#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010
11namespace quic {
12namespace simulator {
13
14Switch::Switch(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -070015 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -050016 SwitchPortNumber port_count,
17 QuicByteCount queue_capacity) {
18 for (size_t port_number = 1; port_number <= port_count; port_number++) {
19 ports_.emplace_back(simulator,
QUICHE team6dcf6ab2019-12-11 10:10:51 -080020 quiche::QuicheStrCat(name, " (port ", port_number, ")"),
21 this, port_number, queue_capacity);
QUICHE teama6ef0a62019-03-07 20:34:33 -050022 }
23}
24
25Switch::~Switch() {}
26
27Switch::Port::Port(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -070028 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -050029 Switch* parent,
30 SwitchPortNumber port_number,
31 QuicByteCount queue_capacity)
32 : Endpoint(simulator, name),
33 parent_(parent),
34 port_number_(port_number),
35 connected_(false),
36 queue_(simulator,
QUICHE team6dcf6ab2019-12-11 10:10:51 -080037 quiche::QuicheStringPrintf("%s (queue)", name.c_str()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050038 queue_capacity) {}
39
40void Switch::Port::AcceptPacket(std::unique_ptr<Packet> packet) {
41 parent_->DispatchPacket(port_number_, std::move(packet));
42}
43
44void Switch::Port::EnqueuePacket(std::unique_ptr<Packet> packet) {
45 queue_.AcceptPacket(std::move(packet));
46}
47
48UnconstrainedPortInterface* Switch::Port::GetRxPort() {
49 return this;
50}
51
52void Switch::Port::SetTxPort(ConstrainedPortInterface* port) {
53 queue_.set_tx_port(port);
54 connected_ = true;
55}
56
57void Switch::Port::Act() {}
58
59void Switch::DispatchPacket(SwitchPortNumber port_number,
60 std::unique_ptr<Packet> packet) {
61 Port* source_port = &ports_[port_number - 1];
62 const auto source_mapping_it = switching_table_.find(packet->source);
63 if (source_mapping_it == switching_table_.end()) {
64 switching_table_.insert(std::make_pair(packet->source, source_port));
65 }
66
67 const auto destination_mapping_it =
68 switching_table_.find(packet->destination);
69 if (destination_mapping_it != switching_table_.end()) {
70 destination_mapping_it->second->EnqueuePacket(std::move(packet));
71 return;
72 }
73
74 // If no mapping is available yet, broadcast the packet to all ports
75 // different from the source.
76 for (Port& egress_port : ports_) {
77 if (!egress_port.connected()) {
78 continue;
79 }
vasilvv0fc587f2019-09-06 13:33:08 -070080 egress_port.EnqueuePacket(std::make_unique<Packet>(*packet));
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 }
82}
83
84} // namespace simulator
85} // namespace quic