L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
mac_table.h
1/*
2 * Copyright (C) 2016-2017, 2020, 2022-2024 Kernkonzept GmbH.
3 * Author(s): Jean Wolter <jean.wolter@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8
9#include "mac_addr.h"
10#include "port.h"
11
12#include <array>
13#include <map>
14#include <algorithm>
38template<std::size_t Size = 1024U>
40{
41public:
42 Mac_table()
43 : _mac_table(),
44 _entries(),
45 _rr_index(0U)
46 {}
47
57 {
58 auto entry = _mac_table.find(dst);
59 return (entry != _mac_table.end()) ? entry->second->port : nullptr;
60 }
61
74 void learn(Mac_addr src, Virtio_port *port)
75 {
76 Dbg info(Dbg::Port, Dbg::Info);
77
78 if (L4_UNLIKELY(info.is_active()))
79 {
80 // check whether we already know about src mac
81 auto *p = lookup(src);
82 if (!p || p != port)
83 {
84 info.printf("%s %-20s -> ", !p ? "learned " : "replaced",
85 port->get_name());
86 src.print(info);
87 info.cprintf("\n");
88 }
89 }
90
91 auto status = _mac_table.emplace(src, &_entries[_rr_index]);
92 if (L4_UNLIKELY(status.second))
93 {
94 if (_entries[_rr_index].port)
95 {
96 // remove old entry
97 _mac_table.erase(_entries[_rr_index].addr);
98 }
99 // Set/Replace port and mac address
100 _entries[_rr_index].port = port;
101 _entries[_rr_index].addr = src;
102 _rr_index = (_rr_index + 1U) % Size;
103 }
104 else
105 {
106 // Update port to allow for movement of client between ports
107 status.first->second->port = port;
108 }
109 }
110
122 void flush(Virtio_port *port)
123 {
124 typedef std::pair<const Mac_addr, Entry*> TableEntry;
125
126 auto iter = _mac_table.begin();
127 while ((iter = std::find_if(iter, _mac_table.end(),
128 [port](TableEntry const &p)
129 { return p.second->port == port; }))
130 != _mac_table.end())
131 {
132 iter->second->port = nullptr;
133 iter->second->addr = Mac_addr::Addr_unknown;
134 iter = _mac_table.erase(iter);
135 }
136
137 assert(std::find_if(_mac_table.begin(), _mac_table.end(),
138 [port](TableEntry const &p)
139 { return p.second->port == port; }) == _mac_table.end());
140 }
141
142private:
149 struct Entry {
150 Virtio_port *port;
151 Mac_addr addr;
152
153 Entry()
154 : port(nullptr),
155 addr(Mac_addr::Addr_unknown)
156 {}
157 };
158
159 std::map<Mac_addr, Entry*> _mac_table;
160 std::array<Entry, Size> _entries;
161 size_t _rr_index;
162};
A wrapper class around the value of a MAC address.
Definition mac_addr.h:20
Mac_table manages a 1:n association between ports and MAC addresses.
Definition mac_table.h:40
void flush(Virtio_port *port)
Flush all associations with a given port.
Definition mac_table.h:122
Virtio_port * lookup(Mac_addr dst) const
Find the destination port for a MAC address.
Definition mac_table.h:56
void learn(Mac_addr src, Virtio_port *port)
Learn a MAC address (add it to the MAC table).
Definition mac_table.h:74
A Port on the Virtio Net Switch.
Definition port.h:36
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:275