Skip to content

Commit f1b1f05

Browse files
authored
[vslib]Add MACsec Filters (sonic-net#713)
All filters will be installed in HostInterfaceInfo to filter the EAPOL and data traffic. The MACsecEgressFilter will forward EAPOL packets to eth device and forward data packets to MACsec device. The MACsecIngressFilter will forward EAPOL packets to Ethernet device and drop all data packets. Because the data packets will be forwarded to MACsec device by Linux kernel. The TrafficFilterPipes provides an interfaces to add more filters for future functions.
1 parent a5cfa36 commit f1b1f05

9 files changed

+363
-0
lines changed

vslib/inc/MACsecEgressFilter.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include "MACsecFilter.h"
4+
5+
namespace saivs
6+
{
7+
class MACsecEgressFilter : public MACsecFilter
8+
{
9+
public:
10+
MACsecEgressFilter(
11+
_In_ const std::string &macsecInterfaceName);
12+
13+
virtual ~MACsecEgressFilter() = default;
14+
15+
protected:
16+
virtual FilterStatus forward(
17+
_In_ const void *buffer,
18+
_In_ size_t length) override;
19+
};
20+
}

vslib/inc/MACsecFilter.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "TrafficFilter.h"
4+
5+
#include <string>
6+
7+
namespace saivs
8+
{
9+
class MACsecFilter :
10+
public TrafficFilter
11+
{
12+
public:
13+
MACsecFilter(
14+
_In_ const std::string &macsecInterfaceName);
15+
16+
virtual ~MACsecFilter() = default;
17+
18+
virtual FilterStatus execute(
19+
_Inout_ void *buffer,
20+
_Inout_ size_t &length) override;
21+
22+
void enable_macsec_device(
23+
_In_ bool enable);
24+
25+
void set_macsec_fd(
26+
_In_ int macsecfd);
27+
28+
protected:
29+
virtual FilterStatus forward(
30+
_In_ const void *buffer,
31+
_In_ size_t length) = 0;
32+
33+
bool m_macsec_device_enable;
34+
35+
int m_macsecfd;
36+
37+
const std::string m_macsec_interface_name;
38+
};
39+
}

vslib/inc/MACsecIngressFilter.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include "MACsecFilter.h"
4+
5+
namespace saivs
6+
{
7+
class MACsecIngressFilter :
8+
public MACsecFilter
9+
{
10+
public:
11+
MACsecIngressFilter(
12+
_In_ const std::string &macsecInterfaceName);
13+
14+
virtual ~MACsecIngressFilter() = default;
15+
16+
protected:
17+
virtual FilterStatus forward(
18+
_In_ const void *buffer,
19+
_In_ size_t length) override;
20+
};
21+
}

vslib/inc/TrafficFilter.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 <sys/types.h>
6+
7+
namespace saivs
8+
{
9+
enum FilterPriority
10+
{
11+
MACSEC_FILTER,
12+
};
13+
14+
class TrafficFilter
15+
{
16+
public:
17+
enum FilterStatus
18+
{
19+
CONTINUE,
20+
TERMINATE,
21+
ERROR,
22+
};
23+
24+
TrafficFilter() = default;
25+
26+
virtual ~TrafficFilter() = default;
27+
28+
virtual FilterStatus execute(
29+
_Inout_ void *buffer,
30+
_Inout_ size_t &length) = 0;
31+
};
32+
}

vslib/inc/TrafficFilterPipes.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include "TrafficFilter.h"
4+
5+
#include <memory>
6+
#include <map>
7+
#include <mutex>
8+
9+
namespace saivs
10+
{
11+
class TrafficFilterPipes
12+
{
13+
public:
14+
TrafficFilterPipes() = default;
15+
16+
virtual ~TrafficFilterPipes() = default;
17+
18+
bool installFilter(
19+
_In_ int priority,
20+
_In_ std::shared_ptr<TrafficFilter> filter);
21+
22+
bool uninstallFilter(
23+
_In_ std::shared_ptr<TrafficFilter> filter);
24+
25+
TrafficFilter::FilterStatus execute(
26+
_Inout_ void *buffer,
27+
_Inout_ size_t &length);
28+
29+
private:
30+
typedef std::map<int, std::shared_ptr<TrafficFilter> > FilterPriorityQueue;
31+
32+
std::mutex m_mutex;
33+
FilterPriorityQueue m_filters;
34+
};
35+
}

vslib/src/MACsecEgressFilter.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "MACsecEgressFilter.h"
2+
3+
#include <swss/logger.h>
4+
5+
#include <unistd.h>
6+
#include <string.h>
7+
8+
using namespace saivs;
9+
10+
MACsecEgressFilter::MACsecEgressFilter(
11+
_In_ const std::string &macsecInterfaceName):
12+
MACsecFilter(macsecInterfaceName)
13+
{
14+
SWSS_LOG_ENTER();
15+
16+
// empty intentionally
17+
}
18+
19+
TrafficFilter::FilterStatus MACsecEgressFilter::forward(
20+
_In_ const void *buffer,
21+
_In_ size_t length)
22+
{
23+
SWSS_LOG_ENTER();
24+
25+
if (write(m_macsecfd, buffer, length) < 0)
26+
{
27+
if (errno != ENETDOWN && errno != EIO)
28+
{
29+
SWSS_LOG_ERROR(
30+
"failed to write to macsec device %s fd %d, errno(%d): %s",
31+
m_macsecInterfaceName.c_str(),
32+
m_macsecfd,
33+
errno,
34+
strerror(errno));
35+
}
36+
37+
if (errno == EBADF)
38+
{
39+
SWSS_LOG_ERROR(
40+
"ending thread for macsec device %s fd %d",
41+
m_macsecInterfaceName.c_str(),
42+
m_macsecfd);
43+
44+
return TrafficFilter::ERROR;
45+
}
46+
}
47+
48+
return TrafficFilter::TERMINATE;
49+
}

vslib/src/MACsecFilter.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "MACsecFilter.h"
2+
3+
#include "swss/logger.h"
4+
#include "swss/select.h"
5+
6+
#include <sys/socket.h>
7+
#include <linux/if_packet.h>
8+
#include <linux/if_ether.h>
9+
#include <arpa/inet.h>
10+
#include <net/if.h>
11+
12+
using namespace saivs;
13+
14+
#define EAPOL_ETHER_TYPE (0x888e)
15+
16+
MACsecFilter::MACsecFilter(
17+
_In_ const std::string &macsecInterfaceName):
18+
m_macsecDeviceEnable(false),
19+
m_macsecfd(0),
20+
m_macsecInterfaceName(macsecInterfaceName)
21+
{
22+
SWSS_LOG_ENTER();
23+
24+
// empty intentionally
25+
}
26+
27+
void MACsecFilter::enable_macsec_device(
28+
_In_ bool enable)
29+
{
30+
SWSS_LOG_ENTER();
31+
32+
m_macsecDeviceEnable = enable;
33+
}
34+
35+
void MACsecFilter::set_macsec_fd(
36+
_In_ int macsecfd)
37+
{
38+
SWSS_LOG_ENTER();
39+
40+
m_macsecfd = macsecfd;
41+
}
42+
43+
TrafficFilter::FilterStatus MACsecFilter::execute(
44+
_Inout_ void *buffer,
45+
_Inout_ size_t &length)
46+
{
47+
SWSS_LOG_ENTER();
48+
49+
auto mac_hdr = static_cast<const ethhdr *>(buffer);
50+
51+
if (ntohs(mac_hdr->h_proto) == EAPOL_ETHER_TYPE)
52+
{
53+
// EAPOL traffic will never be delivered to MACsec device
54+
return TrafficFilter::CONTINUE;
55+
}
56+
57+
if (m_macsecDeviceEnable)
58+
{
59+
return forward(buffer, length);
60+
}
61+
62+
// Drop all non-EAPOL packets if macsec device haven't been enable.
63+
return TrafficFilter::TERMINATE;
64+
}

vslib/src/MACsecIngressFilter.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "MACsecIngressFilter.h"
2+
3+
#include "swss/logger.h"
4+
5+
#include <unistd.h>
6+
#include <string.h>
7+
8+
using namespace saivs;
9+
10+
MACsecIngressFilter::MACsecIngressFilter(
11+
_In_ const std::string &macsecInterfaceName) :
12+
MACsecFilter(macsecInterfaceName)
13+
{
14+
SWSS_LOG_ENTER();
15+
16+
// empty intentionally
17+
}
18+
19+
TrafficFilter::FilterStatus MACsecIngressFilter::forward(
20+
_In_ const void *buffer,
21+
_In_ size_t length)
22+
{
23+
SWSS_LOG_ENTER();
24+
25+
// MACsec interface will automatically forward ingress MACsec traffic
26+
// by Linux Kernel.
27+
// So this filter just need to drop all ingress MACsec traffic directly
28+
29+
return TrafficFilter::TERMINATE;
30+
}

vslib/src/TrafficFilterPipes.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "TrafficFilterPipes.h"
2+
3+
#include "swss/logger.h"
4+
5+
using namespace saivs;
6+
7+
bool TrafficFilterPipes::installFilter(
8+
_In_ int priority,
9+
_In_ std::shared_ptr<TrafficFilter> filter)
10+
{
11+
SWSS_LOG_ENTER();
12+
13+
std::unique_lock<std::mutex> guard(m_mutex);
14+
15+
return m_filters.emplace(priority, filter).second;
16+
}
17+
18+
bool TrafficFilterPipes::uninstallFilter(
19+
_In_ std::shared_ptr<TrafficFilter> filter)
20+
{
21+
SWSS_LOG_ENTER();
22+
23+
std::unique_lock<std::mutex> guard(m_mutex);
24+
25+
for (auto itr = m_filters.begin();
26+
itr != m_filters.end();
27+
itr ++)
28+
{
29+
if (itr->second == filter)
30+
{
31+
m_filters.erase(itr);
32+
33+
return true;
34+
}
35+
}
36+
37+
return false;
38+
}
39+
40+
TrafficFilter::FilterStatus TrafficFilterPipes::execute(
41+
_Inout_ void *buffer,
42+
_Inout_ size_t &length)
43+
{
44+
SWSS_LOG_ENTER();
45+
46+
std::unique_lock<std::mutex> guard(m_mutex);
47+
TrafficFilter::FilterStatus ret = TrafficFilter::CONTINUE;
48+
49+
for (auto itr = m_filters.begin(); itr != m_filters.end();)
50+
{
51+
auto filter = itr->second;
52+
53+
if (filter)
54+
{
55+
ret = filter->execute(buffer, length);
56+
57+
if (ret == TrafficFilter::CONTINUE)
58+
{
59+
itr ++;
60+
}
61+
else
62+
{
63+
break;
64+
}
65+
}
66+
else
67+
{
68+
itr = m_filters.erase(itr);
69+
}
70+
}
71+
72+
return ret;
73+
}

0 commit comments

Comments
 (0)