Skip to content

Commit 6dfad66

Browse files
authored
[vslib]Add MACsec forward and filters to HostInterfaceInfo (#719)
Add MACsec filter before VLAN Tag and FDB event processing. Refer: MACsec in VLAN-aware Bridges
1 parent 2fb5230 commit 6dfad66

10 files changed

+288
-96
lines changed

vslib/inc/HostInterfaceInfo.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ extern "C" {
55
}
66

77
#include "EventQueue.h"
8+
#include "TrafficFilterPipes.h"
9+
#include "TrafficForwarder.h"
810

911
#include "swss/selectableevent.h"
1012

@@ -14,7 +16,8 @@ extern "C" {
1416

1517
namespace saivs
1618
{
17-
class HostInterfaceInfo
19+
class HostInterfaceInfo :
20+
public TrafficForwarder
1821
{
1922
private:
2023

@@ -38,6 +41,20 @@ namespace saivs
3841
_In_ const uint8_t *buffer,
3942
_In_ size_t size) const;
4043

44+
bool installEth2TapFilter(
45+
_In_ int priority,
46+
_In_ std::shared_ptr<TrafficFilter> filter);
47+
48+
bool uninstallEth2TapFilter(
49+
_In_ std::shared_ptr<TrafficFilter> filter);
50+
51+
bool installTap2EthFilter(
52+
_In_ int priority,
53+
_In_ std::shared_ptr<TrafficFilter> filter);
54+
55+
bool uninstallTap2EthFilter(
56+
_In_ std::shared_ptr<TrafficFilter> filter);
57+
4158
private:
4259

4360
void veth2tap_fun();
@@ -58,13 +75,16 @@ namespace saivs
5875

5976
std::shared_ptr<EventQueue> m_eventQueue;
6077

61-
private:
62-
6378
int m_tapfd;
6479

80+
private:
81+
6582
std::shared_ptr<std::thread> m_e2t;
6683
std::shared_ptr<std::thread> m_t2e;
6784

85+
TrafficFilterPipes m_e2tFilters;
86+
TrafficFilterPipes m_t2eFilters;
87+
6888
swss::SelectableEvent m_e2tEvent;
6989
swss::SelectableEvent m_t2eEvent;
7090
};

vslib/inc/MACsecFilter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ namespace saivs
3030
_In_ const void *buffer,
3131
_In_ size_t length) = 0;
3232

33-
bool m_macsec_device_enable;
33+
bool m_macsecDeviceEnable;
3434

3535
int m_macsecfd;
3636

37-
const std::string m_macsec_interface_name;
37+
const std::string m_macsecInterfaceName;
3838
};
3939
}

vslib/inc/MACsecForwarder.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
#include "HostInterfaceInfo.h"
4+
#include "TrafficForwarder.h"
5+
36
#include "swss/sal.h"
47
#include "swss/selectableevent.h"
58

@@ -9,12 +12,13 @@
912

1013
namespace saivs
1114
{
12-
class MACsecForwarder
15+
class MACsecForwarder :
16+
public TrafficForwarder
1317
{
1418
public:
1519
MACsecForwarder(
1620
_In_ const std::string &macsecInterfaceName,
17-
_In_ int tapfd);
21+
_In_ std::shared_ptr<HostInterfaceInfo> info);
1822

1923
virtual ~MACsecForwarder();
2024

@@ -23,7 +27,6 @@ namespace saivs
2327
void forward();
2428

2529
private:
26-
int m_tapfd;
2730
int m_macsecfd;
2831

2932
const std::string m_macsecInterfaceName;
@@ -33,5 +36,7 @@ namespace saivs
3336
swss::SelectableEvent m_exitEvent;
3437

3538
std::shared_ptr<std::thread> m_forwardThread;
39+
40+
std::shared_ptr<HostInterfaceInfo> m_info;
3641
};
3742
}

vslib/inc/SwitchStateBase.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,11 @@ namespace saivs
363363
sai_status_t removeDebugCounter(
364364
_In_ sai_object_id_t objectId);
365365

366+
public:
367+
368+
static int promisc(
369+
_In_ const char *dev);
370+
366371
protected: // custom hostif
367372

368373
sai_status_t createHostif(
@@ -394,9 +399,6 @@ namespace saivs
394399
_In_ const char *dev,
395400
_In_ const sai_mac_t& mac);
396401

397-
static int promisc(
398-
_In_ const char *dev);
399-
400402
static int get_default_gw_mac_address(
401403
_Out_ sai_mac_t& mac);
402404

vslib/inc/TrafficForwarder.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include "swss/sal.h"
4+
5+
#include <stddef.h>
6+
#include <sys/socket.h>
7+
8+
namespace saivs
9+
{
10+
static constexpr size_t ETH_FRAME_BUFFER_SIZE = 0x4000;
11+
static constexpr size_t CONTROL_MESSAGE_BUFFER_SIZE = 0x1000;
12+
13+
class TrafficForwarder
14+
{
15+
public:
16+
virtual ~TrafficForwarder() = default;
17+
18+
protected:
19+
TrafficForwarder() = default;
20+
21+
static void addVlanTag(
22+
_Inout_ unsigned char *buffer,
23+
_Inout_ size_t &length,
24+
_Inout_ struct msghdr &msg);
25+
26+
virtual bool sendTo(
27+
_In_ int fd,
28+
_In_ const unsigned char *buffer,
29+
_In_ size_t length) const;
30+
31+
};
32+
}

vslib/src/HostInterfaceInfo.cpp

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,39 @@ void HostInterfaceInfo::async_process_packet_for_fdb_event(
9090
m_eventQueue->enqueue(std::make_shared<Event>(EventType::EVENT_TYPE_PACKET, payload));
9191
}
9292

93-
#define ETH_FRAME_BUFFER_SIZE (0x4000)
94-
#define CONTROL_MESSAGE_BUFFER_SIZE (0x1000)
95-
#define IEEE_8021Q_ETHER_TYPE (0x8100)
96-
#define MAC_ADDRESS_SIZE (6)
97-
#define VLAN_TAG_SIZE (4)
93+
bool HostInterfaceInfo::installEth2TapFilter(
94+
_In_ int priority,
95+
_In_ std::shared_ptr<TrafficFilter> filter)
96+
{
97+
SWSS_LOG_ENTER();
98+
99+
return m_e2tFilters.installFilter(priority, filter);
100+
}
101+
102+
bool HostInterfaceInfo::uninstallEth2TapFilter(
103+
_In_ std::shared_ptr<TrafficFilter> filter)
104+
{
105+
SWSS_LOG_ENTER();
106+
107+
return m_e2tFilters.uninstallFilter(filter);
108+
}
109+
110+
bool HostInterfaceInfo::installTap2EthFilter(
111+
_In_ int priority,
112+
_In_ std::shared_ptr<TrafficFilter> filter)
113+
{
114+
SWSS_LOG_ENTER();
115+
116+
return m_t2eFilters.installFilter(priority, filter);
117+
}
118+
119+
bool HostInterfaceInfo::uninstallTap2EthFilter(
120+
_In_ std::shared_ptr<TrafficFilter> filter)
121+
{
122+
SWSS_LOG_ENTER();
123+
124+
return m_t2eFilters.uninstallFilter(filter);
125+
}
98126

99127
void HostInterfaceInfo::veth2tap_fun()
100128
{
@@ -161,63 +189,28 @@ void HostInterfaceInfo::veth2tap_fun()
161189
continue;
162190
}
163191

164-
struct cmsghdr *cmsg;
192+
// Buffer include the ingress packets
193+
// MACsec scenario: EAPOL packets and encrypted packets
194+
size_t length = static_cast<size_t>(size);
195+
auto ret = m_e2tFilters.execute(buffer, length);
165196

166-
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
197+
if (ret == TrafficFilter::TERMINATE)
167198
{
168-
if (cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA)
169-
continue;
170-
171-
struct tpacket_auxdata* aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
172-
173-
if ((aux->tp_status & TP_STATUS_VLAN_VALID) &&
174-
(aux->tp_status & TP_STATUS_VLAN_TPID_VALID))
175-
{
176-
SWSS_LOG_DEBUG("got vlan tci: 0x%x, vlanid: %d", aux->tp_vlan_tci, aux->tp_vlan_tci & 0xFFF);
177-
178-
// inject vlan tag into frame
179-
180-
// for overlapping buffers
181-
memmove(buffer + 2 * MAC_ADDRESS_SIZE + VLAN_TAG_SIZE,
182-
buffer + 2 * MAC_ADDRESS_SIZE,
183-
size - (2 * MAC_ADDRESS_SIZE));
184-
185-
uint16_t tci = htons(aux->tp_vlan_tci);
186-
uint16_t tpid = htons(IEEE_8021Q_ETHER_TYPE);
187-
188-
uint8_t* pvlan = (uint8_t *)(buffer + 2 * MAC_ADDRESS_SIZE);
189-
memcpy(pvlan, &tpid, sizeof(uint16_t));
190-
memcpy(pvlan + sizeof(uint16_t), &tci, sizeof(uint16_t));
191-
192-
size += VLAN_TAG_SIZE;
193-
194-
break;
195-
}
199+
continue;
196200
}
197-
198-
async_process_packet_for_fdb_event(buffer, size);
199-
200-
if (write(m_tapfd, buffer, size) < 0)
201+
else if (ret == TrafficFilter::ERROR)
201202
{
202-
/*
203-
* We filter out EIO because of this patch:
204-
* https://github.com/torvalds/linux/commit/1bd4978a88ac2589f3105f599b1d404a312fb7f6
205-
*/
203+
// Error log should be recorded in filter
204+
return;
205+
}
206206

207-
if (errno != ENETDOWN && errno != EIO)
208-
{
209-
SWSS_LOG_ERROR("failed to write to tap device fd %d, errno(%d): %s",
210-
m_tapfd, errno, strerror(errno));
211-
}
207+
addVlanTag(buffer, length, msg);
212208

213-
if (errno == EBADF)
214-
{
215-
// bad file descriptor, just end thread
216-
SWSS_LOG_NOTICE("ending thread for tap fd %d", m_tapfd);
217-
return;
218-
}
209+
async_process_packet_for_fdb_event(buffer, length);
219210

220-
continue;
211+
if (!sendTo(m_tapfd, buffer, length))
212+
{
213+
break;
221214
}
222215
}
223216

@@ -268,6 +261,22 @@ void HostInterfaceInfo::tap2veth_fun()
268261
continue;
269262
}
270263

264+
// Buffer include the egress packets
265+
// MACsec scenario: EAPOL packets and plaintext packets
266+
size_t length = static_cast<size_t>(size);
267+
auto ret = m_t2eFilters.execute(buffer, length);
268+
size = static_cast<ssize_t>(length);
269+
270+
if (ret == TrafficFilter::TERMINATE)
271+
{
272+
continue;
273+
}
274+
else if (ret == TrafficFilter::ERROR)
275+
{
276+
// Error log should be recorded in filter
277+
return;
278+
}
279+
271280
if (write(m_packet_socket, buffer, (int)size) < 0)
272281
{
273282
if (errno != ENETDOWN)

0 commit comments

Comments
 (0)