Skip to content

Commit

Permalink
[vslib]Add MACsec forward and filters to HostInterfaceInfo (sonic-net…
Browse files Browse the repository at this point in the history
…#719)

Add MACsec filter before VLAN Tag and FDB event processing.
Refer: MACsec in VLAN-aware Bridges
  • Loading branch information
Pterosaur authored Dec 1, 2020
1 parent 2fb5230 commit 6dfad66
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 96 deletions.
26 changes: 23 additions & 3 deletions vslib/inc/HostInterfaceInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ extern "C" {
}

#include "EventQueue.h"
#include "TrafficFilterPipes.h"
#include "TrafficForwarder.h"

#include "swss/selectableevent.h"

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

namespace saivs
{
class HostInterfaceInfo
class HostInterfaceInfo :
public TrafficForwarder
{
private:

Expand All @@ -38,6 +41,20 @@ namespace saivs
_In_ const uint8_t *buffer,
_In_ size_t size) const;

bool installEth2TapFilter(
_In_ int priority,
_In_ std::shared_ptr<TrafficFilter> filter);

bool uninstallEth2TapFilter(
_In_ std::shared_ptr<TrafficFilter> filter);

bool installTap2EthFilter(
_In_ int priority,
_In_ std::shared_ptr<TrafficFilter> filter);

bool uninstallTap2EthFilter(
_In_ std::shared_ptr<TrafficFilter> filter);

private:

void veth2tap_fun();
Expand All @@ -58,13 +75,16 @@ namespace saivs

std::shared_ptr<EventQueue> m_eventQueue;

private:

int m_tapfd;

private:

std::shared_ptr<std::thread> m_e2t;
std::shared_ptr<std::thread> m_t2e;

TrafficFilterPipes m_e2tFilters;
TrafficFilterPipes m_t2eFilters;

swss::SelectableEvent m_e2tEvent;
swss::SelectableEvent m_t2eEvent;
};
Expand Down
4 changes: 2 additions & 2 deletions vslib/inc/MACsecFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ namespace saivs
_In_ const void *buffer,
_In_ size_t length) = 0;

bool m_macsec_device_enable;
bool m_macsecDeviceEnable;

int m_macsecfd;

const std::string m_macsec_interface_name;
const std::string m_macsecInterfaceName;
};
}
11 changes: 8 additions & 3 deletions vslib/inc/MACsecForwarder.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include "HostInterfaceInfo.h"
#include "TrafficForwarder.h"

#include "swss/sal.h"
#include "swss/selectableevent.h"

Expand All @@ -9,12 +12,13 @@

namespace saivs
{
class MACsecForwarder
class MACsecForwarder :
public TrafficForwarder
{
public:
MACsecForwarder(
_In_ const std::string &macsecInterfaceName,
_In_ int tapfd);
_In_ std::shared_ptr<HostInterfaceInfo> info);

virtual ~MACsecForwarder();

Expand All @@ -23,7 +27,6 @@ namespace saivs
void forward();

private:
int m_tapfd;
int m_macsecfd;

const std::string m_macsecInterfaceName;
Expand All @@ -33,5 +36,7 @@ namespace saivs
swss::SelectableEvent m_exitEvent;

std::shared_ptr<std::thread> m_forwardThread;

std::shared_ptr<HostInterfaceInfo> m_info;
};
}
8 changes: 5 additions & 3 deletions vslib/inc/SwitchStateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ namespace saivs
sai_status_t removeDebugCounter(
_In_ sai_object_id_t objectId);

public:

static int promisc(
_In_ const char *dev);

protected: // custom hostif

sai_status_t createHostif(
Expand Down Expand Up @@ -394,9 +399,6 @@ namespace saivs
_In_ const char *dev,
_In_ const sai_mac_t& mac);

static int promisc(
_In_ const char *dev);

static int get_default_gw_mac_address(
_Out_ sai_mac_t& mac);

Expand Down
32 changes: 32 additions & 0 deletions vslib/inc/TrafficForwarder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include "swss/sal.h"

#include <stddef.h>
#include <sys/socket.h>

namespace saivs
{
static constexpr size_t ETH_FRAME_BUFFER_SIZE = 0x4000;
static constexpr size_t CONTROL_MESSAGE_BUFFER_SIZE = 0x1000;

class TrafficForwarder
{
public:
virtual ~TrafficForwarder() = default;

protected:
TrafficForwarder() = default;

static void addVlanTag(
_Inout_ unsigned char *buffer,
_Inout_ size_t &length,
_Inout_ struct msghdr &msg);

virtual bool sendTo(
_In_ int fd,
_In_ const unsigned char *buffer,
_In_ size_t length) const;

};
}
119 changes: 64 additions & 55 deletions vslib/src/HostInterfaceInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,39 @@ void HostInterfaceInfo::async_process_packet_for_fdb_event(
m_eventQueue->enqueue(std::make_shared<Event>(EventType::EVENT_TYPE_PACKET, payload));
}

#define ETH_FRAME_BUFFER_SIZE (0x4000)
#define CONTROL_MESSAGE_BUFFER_SIZE (0x1000)
#define IEEE_8021Q_ETHER_TYPE (0x8100)
#define MAC_ADDRESS_SIZE (6)
#define VLAN_TAG_SIZE (4)
bool HostInterfaceInfo::installEth2TapFilter(
_In_ int priority,
_In_ std::shared_ptr<TrafficFilter> filter)
{
SWSS_LOG_ENTER();

return m_e2tFilters.installFilter(priority, filter);
}

bool HostInterfaceInfo::uninstallEth2TapFilter(
_In_ std::shared_ptr<TrafficFilter> filter)
{
SWSS_LOG_ENTER();

return m_e2tFilters.uninstallFilter(filter);
}

bool HostInterfaceInfo::installTap2EthFilter(
_In_ int priority,
_In_ std::shared_ptr<TrafficFilter> filter)
{
SWSS_LOG_ENTER();

return m_t2eFilters.installFilter(priority, filter);
}

bool HostInterfaceInfo::uninstallTap2EthFilter(
_In_ std::shared_ptr<TrafficFilter> filter)
{
SWSS_LOG_ENTER();

return m_t2eFilters.uninstallFilter(filter);
}

void HostInterfaceInfo::veth2tap_fun()
{
Expand Down Expand Up @@ -161,63 +189,28 @@ void HostInterfaceInfo::veth2tap_fun()
continue;
}

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

for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
if (ret == TrafficFilter::TERMINATE)
{
if (cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA)
continue;

struct tpacket_auxdata* aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);

if ((aux->tp_status & TP_STATUS_VLAN_VALID) &&
(aux->tp_status & TP_STATUS_VLAN_TPID_VALID))
{
SWSS_LOG_DEBUG("got vlan tci: 0x%x, vlanid: %d", aux->tp_vlan_tci, aux->tp_vlan_tci & 0xFFF);

// inject vlan tag into frame

// for overlapping buffers
memmove(buffer + 2 * MAC_ADDRESS_SIZE + VLAN_TAG_SIZE,
buffer + 2 * MAC_ADDRESS_SIZE,
size - (2 * MAC_ADDRESS_SIZE));

uint16_t tci = htons(aux->tp_vlan_tci);
uint16_t tpid = htons(IEEE_8021Q_ETHER_TYPE);

uint8_t* pvlan = (uint8_t *)(buffer + 2 * MAC_ADDRESS_SIZE);
memcpy(pvlan, &tpid, sizeof(uint16_t));
memcpy(pvlan + sizeof(uint16_t), &tci, sizeof(uint16_t));

size += VLAN_TAG_SIZE;

break;
}
continue;
}

async_process_packet_for_fdb_event(buffer, size);

if (write(m_tapfd, buffer, size) < 0)
else if (ret == TrafficFilter::ERROR)
{
/*
* We filter out EIO because of this patch:
* https://github.com/torvalds/linux/commit/1bd4978a88ac2589f3105f599b1d404a312fb7f6
*/
// Error log should be recorded in filter
return;
}

if (errno != ENETDOWN && errno != EIO)
{
SWSS_LOG_ERROR("failed to write to tap device fd %d, errno(%d): %s",
m_tapfd, errno, strerror(errno));
}
addVlanTag(buffer, length, msg);

if (errno == EBADF)
{
// bad file descriptor, just end thread
SWSS_LOG_NOTICE("ending thread for tap fd %d", m_tapfd);
return;
}
async_process_packet_for_fdb_event(buffer, length);

continue;
if (!sendTo(m_tapfd, buffer, length))
{
break;
}
}

Expand Down Expand Up @@ -268,6 +261,22 @@ void HostInterfaceInfo::tap2veth_fun()
continue;
}

// Buffer include the egress packets
// MACsec scenario: EAPOL packets and plaintext packets
size_t length = static_cast<size_t>(size);
auto ret = m_t2eFilters.execute(buffer, length);
size = static_cast<ssize_t>(length);

if (ret == TrafficFilter::TERMINATE)
{
continue;
}
else if (ret == TrafficFilter::ERROR)
{
// Error log should be recorded in filter
return;
}

if (write(m_packet_socket, buffer, (int)size) < 0)
{
if (errno != ENETDOWN)
Expand Down
Loading

0 comments on commit 6dfad66

Please sign in to comment.