Skip to content

Commit

Permalink
[posix] add netif TUN Ip6 Sending (#2452)
Browse files Browse the repository at this point in the history
In specific, when a packet from the system is sent to the wpan
interface, the Netif module will do the Ip6 sending. In this commit
the actual sending (let NCP send the IP6 packet) hasn't been
implemented and an empty implementation is used.

The commit also adds a unit test to verify IP packet sent through wpan
interface can be successfully handled in netif.
  • Loading branch information
Irving-cl authored Sep 2, 2024
1 parent 2a85a7b commit 3874d96
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/ncp/ncp_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ void NcpHost::Init(void)
{
otSysInit(&mConfig);
mNcpSpinel.Init(mSpinelDriver, *this);
mNetif.Init(mConfig.mInterfaceName);
mNetif.Init(mConfig.mInterfaceName,
[this](const uint8_t *aData, uint16_t aLength) { return mNcpSpinel.Ip6Send(aData, aLength); });

mNcpSpinel.Ip6SetAddressCallback(
[this](const std::vector<Ip6AddressInfo> &aAddrInfos) { mNetif.UpdateIp6UnicastAddresses(aAddrInfos); });
Expand Down
9 changes: 9 additions & 0 deletions src/ncp/ncp_spinel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ void NcpSpinel::Ip6SetEnabled(bool aEnable, AsyncTaskPtr aAsyncTask)
return;
}

otbrError NcpSpinel::Ip6Send(const uint8_t *aData, uint16_t aLength)
{
// TODO: Impelement this function.
OTBR_UNUSED_VARIABLE(aData);
OTBR_UNUSED_VARIABLE(aLength);

return OTBR_ERROR_NONE;
}

void NcpSpinel::ThreadSetEnabled(bool aEnable, AsyncTaskPtr aAsyncTask)
{
otError error = OT_ERROR_NONE;
Expand Down
12 changes: 12 additions & 0 deletions src/ncp/ncp_spinel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,18 @@ class NcpSpinel
mIp6MulticastAddressTableCallback = aCallback;
}

/**
* This methods sends an IP6 datagram through the NCP.
*
* @param[in] aData A pointer to the beginning of the IP6 datagram.
* @param[in] aLength The length of the datagram.
*
* @retval OTBR_ERROR_NONE The datagram is sent to NCP successfully.
* @retval OTBR_ERROR_BUSY NcpSpinel is busy with other requests.
*
*/
otbrError Ip6Send(const uint8_t *aData, uint16_t aLength);

/**
* This method enableds/disables the Thread network on the NCP.
*
Expand Down
57 changes: 56 additions & 1 deletion src/ncp/posix/netif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ Netif::Netif(void)
{
}

otbrError Netif::Init(const std::string &aInterfaceName)
otbrError Netif::Init(const std::string &aInterfaceName, const Ip6SendFunc &aIp6SendFunc)
{
otbrError error = OTBR_ERROR_NONE;

VerifyOrExit(aIp6SendFunc, error = OTBR_ERROR_INVALID_ARGS);
mIp6SendFunc = aIp6SendFunc;

mIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_ERRNO);

Expand All @@ -87,6 +90,35 @@ void Netif::Deinit(void)
Clear();
}

void Netif::Process(const MainloopContext *aContext)
{
if (FD_ISSET(mTunFd, &aContext->mErrorFdSet))
{
close(mTunFd);
DieNow("Error on Tun Fd!");
}

if (FD_ISSET(mTunFd, &aContext->mReadFdSet))
{
ProcessIp6Send();
}
}

void Netif::UpdateFdSet(MainloopContext *aContext)
{
assert(aContext != nullptr);
assert(mTunFd >= 0);
assert(mIpFd >= 0);

FD_SET(mTunFd, &aContext->mReadFdSet);
FD_SET(mTunFd, &aContext->mErrorFdSet);

if (mTunFd > aContext->mMaxFd)
{
aContext->mMaxFd = mTunFd;
}
}

void Netif::UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos)
{
// Remove stale addresses
Expand Down Expand Up @@ -219,6 +251,28 @@ void Netif::Ip6Receive(const uint8_t *aBuf, uint16_t aLen)
}
}

void Netif::ProcessIp6Send(void)
{
ssize_t rval;
uint8_t packet[kIp6Mtu];
otbrError error = OTBR_ERROR_NONE;

rval = read(mTunFd, packet, sizeof(packet));
VerifyOrExit(rval > 0, error = OTBR_ERROR_ERRNO);

otbrLogInfo("Send packet (%hu bytes)", static_cast<uint16_t>(rval));

if (mIp6SendFunc != nullptr)
{
error = mIp6SendFunc(packet, rval);
}
exit:
if (error == OTBR_ERROR_ERRNO)
{
otbrLogInfo("Error reading from Tun Fd: %s", strerror(errno));
}
}

void Netif::Clear(void)
{
if (mTunFd != -1)
Expand All @@ -242,6 +296,7 @@ void Netif::Clear(void)
mNetifIndex = 0;
mIp6UnicastAddresses.clear();
mIp6MulticastAddresses.clear();
mIp6SendFunc = nullptr;
}

} // namespace otbr
12 changes: 10 additions & 2 deletions src/ncp/posix/netif.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,29 @@

#include <net/if.h>

#include <functional>
#include <vector>

#include <openthread/ip6.h>

#include "common/mainloop.hpp"
#include "common/types.hpp"

namespace otbr {

class Netif
{
public:
using Ip6SendFunc = std::function<otbrError(const uint8_t *, uint16_t)>;

Netif(void);

otbrError Init(const std::string &aInterfaceName);
otbrError Init(const std::string &aInterfaceName, const Ip6SendFunc &aIp6SendFunc);
void Deinit(void);

void UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aOtAddrInfos);
void Process(const MainloopContext *aContext);
void UpdateFdSet(MainloopContext *aContext);
void UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos);
otbrError UpdateIp6MulticastAddresses(const std::vector<Ip6Address> &aAddrs);
void SetNetifState(bool aState);

Expand All @@ -71,6 +77,7 @@ class Netif
void SetAddrGenModeToNone(void);
void ProcessUnicastAddressChange(const Ip6AddressInfo &aAddressInfo, bool aIsAdded);
otbrError ProcessMulticastAddressChange(const Ip6Address &aAddress, bool aIsAdded);
void ProcessIp6Send(void);

int mTunFd; ///< Used to exchange IPv6 packets.
int mIpFd; ///< Used to manage IPv6 stack on the network interface.
Expand All @@ -82,6 +89,7 @@ class Netif

std::vector<Ip6AddressInfo> mIp6UnicastAddresses;
std::vector<Ip6Address> mIp6MulticastAddresses;
Ip6SendFunc mIp6SendFunc;
};

} // namespace otbr
Expand Down
Loading

0 comments on commit 3874d96

Please sign in to comment.