blob: 9281f489db4984033f5f0f566dc2a182b6edbbd1 [file] [log] [blame]
/*
*
* Copyright (c) 2014-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file contains headers for the TunnelAgent module that coordinates routing between
* peripheral networks and the Nest Service within the Border Gateway and Mobile devices.
*
*/
#ifndef _WEAVE_TUNNEL_AGENT_H_
#define _WEAVE_TUNNEL_AGENT_H_
#include <Weave/Core/WeaveCore.h>
#include <Weave/Profiles/weave-tunneling/WeaveTunnelCommon.h>
#include <Weave/Profiles/weave-tunneling/WeaveTunnelConnectionMgr.h>
#include <Weave/Profiles/service-directory/ServiceDirectory.h>
#if WEAVE_CONFIG_ENABLE_TUNNELING
#define TUN_DEFAULT_INTF_NAME "weav-tun0"
#define PRIMARY_TUNNEL_DEFAULT_INTF_NAME "wlan0"
#define BACKUP_TUNNEL_DEFAULT_INTF_NAME "ppp0"
#define TUN_INTF_NAME_MAX_LEN (64)
#define WEAVE_ULA_FABRIC_DEFAULT_PREFIX_LEN (48)
#define TUNNEL_PACKET_QUEUE_INVALID_INDEX (-1)
namespace nl {
namespace Weave {
namespace Profiles {
namespace WeaveTunnel {
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
using namespace ::nl::Weave::Profiles::ServiceDirectory;
#endif
class WeaveTunnelConnectionMgr;
/// Platform provided Weave Addressing and Routing routines
namespace Platform {
/**
* @brief
* The set of states for Weave tunnel availability.
*/
typedef enum TunnelAvailabilityMode
{
kMode_Primary = 1, /**< Set when the Weave Service Tunnel is available over the primary interface */
kMode_PrimaryAndBackup = 2, /**< Set when the Weave Service Tunnel is available over both priary and backup interface */
kMode_BackupOnly = 3, /**< Set when the Weave Service Tunnel is available over the backup interface only */
} TunnelAvailabilityMode;
// Following APIs must be implemented by platform:
// Perform address/route assignment tasks when the Weave tunnel interface is brought up.
extern void TunnelInterfaceUp(InterfaceId tunIf);
// Perform address/route deletion tasks when the Weave tunnel interface is brought down.
extern void TunnelInterfaceDown(InterfaceId tunIf);
// Perform address/route assignment tasks when the Service tunnel connection is established.
extern void ServiceTunnelEstablished(InterfaceId tunIf, TunnelAvailabilityMode tunMode);
// Perform address and route assignment tasks when the Service tunnel connection is torn down.
extern void ServiceTunnelDisconnected(InterfaceId tunIf);
/// Perform address and route assignment tasks when the Service tunnel connection avalability state
/// changes.
extern void ServiceTunnelModeChange(InterfaceId tunIf, TunnelAvailabilityMode tunMode);
} // namespace Platform
#if WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
/**
* This structure contains the relevant statistics counters that is common
* to the Primary and Backup Tunnels
*/
typedef struct WeaveTunnelCommonStatistics
{
uint64_t mTxBytesToService; /**< Number of bytes transmitted to the Service. */
uint64_t mRxBytesFromService; /**< Number of bytes received from the Service. */
uint32_t mTxMessagesToService; /**< Number of messages transmitted to the Service. */
uint32_t mRxMessagesFromService; /**< Number of messages received from the Service. */
uint32_t mTunnelDownCount; /**< Counter for the Weave Tunnel Down events. */
uint32_t mTunnelConnAttemptCount; /**< Counter for the Weave Tunnel Connection attempts. */
WEAVE_ERROR mLastTunnelDownError; /**< The Weave error encountered when the tunnel last went down. */
uint64_t mLastTimeTunnelWentDown; /**< Last time Weave Tunnel went Down. */
uint64_t mLastTimeTunnelEstablished; /**< Last time Weave Tunnel was Established. */
} WeaveTunnelCommonStatistics;
/**
* This structure contains the relevant statistics counters for the WeaveTunnel.
*/
typedef struct WeaveTunnelStatistics
{
WeaveTunnelCommonStatistics mPrimaryStats; /**< Primary Weave Tunnel statistics counters. */
uint32_t mDroppedMessagesCount; /**< Number of dropped messages by the WeaveTunnelAgent. */
TunnelType mCurrentActiveTunnel; /**< The Weave tunnel that is currently being used for data traffic. */
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
WeaveTunnelCommonStatistics mBackupStats; /**< Backup Weave Tunnel statistics counters. */
uint32_t mTunnelFailoverCount; /**< Counter for the Weave Tunnel Failover events. */
WEAVE_ERROR mLastTunnelFailoverError; /**< The Weave error encountered when the tunnel last failed over from Primary to Backup. */
uint64_t mLastTimeForTunnelFailover; /**< Last time Weave Tunnel failed over to Backup. */
uint64_t mLastTimeWhenPrimaryAndBackupWentDown; /**< Last time when both Primary and Backup Weave Tunnel went down. */
#endif // WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
} WeaveTunnelStatistics;
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
class WeaveTunnelAgent
{
friend class WeaveTunnelControl;
friend class WeaveTunnelConnectionMgr;
public:
/// States of the Tunnel Agent in relation to its connection(s) to
/// the Service;
typedef enum AgentState
{
kState_NotInitialized = 0, ///<Used to indicate that the Tunnel Agent is not initialized.
kState_Initialized_NoTunnel = 1, ///<Used to indicate that the Tunnel Agent is initialized but no tunnel has been established.
kState_PrimaryTunModeEstablished = 2, ///<Used to indicate that the Primary tunnel to the Service has been established.
kState_BkupOnlyTunModeEstablished = 3, ///<Used to indicate that the Backup tunnel to the Service has been established.
kState_PrimaryAndBkupTunModeEstablished = 4, ///<Used to indicate that both the Primary and the Backup tunnel has been established.
} AgentState;
/// Weave Tunnel flag bits.
typedef enum WeaveTunnelFlags
{
kTunnelFlag_PrimaryEnabled = 0x01, ///< Set when the primary tunnel is enabled.
kTunnelFlag_BackupEnabled = 0x02, ///< Set when the backup tunnel is enabled.
} WeaveTunnelFlags;
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
/// Service Manager pointer to use to lookup and connect to Service.
WeaveServiceManager *mServiceMgr;
#endif
WeaveTunnelAgent(void);
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
/**
* Initialize the Tunnel agent. This creates te Tunnel endpoint object, sets up the tunnel
* interface, initializes member variables, callbacks and WeaveTunnelControl.
*/
WEAVE_ERROR Init(InetLayer *inet, WeaveExchangeManager *exchMgr,
uint64_t dstNodeId, WeaveAuthMode authMode,
WeaveServiceManager *svcMgr,
const char *intfName = TUN_DEFAULT_INTF_NAME,
uint8_t role = kClientRole_BorderGateway,
void *appContext = NULL);
#endif
/**
* Initialize the Tunnel agent. This creates te Tunnel endpoint object, sets up the tunnel
* interface, initializes member variables, callbacks and WeaveTunnelControl.
*/
WEAVE_ERROR Init(InetLayer *inet, WeaveExchangeManager *exchMgr,
uint64_t dstNodeId, IPAddress dstIPAddr, WeaveAuthMode authMode,
const char *intfName = TUN_DEFAULT_INTF_NAME,
uint8_t role = kClientRole_BorderGateway,
void *appContext = NULL);
/**
* Set the WeaveAuthMode for the Tunnel.
*
*/
void SetAuthMode(const WeaveAuthMode authMode);
/**
* Set the destination nodeId, IPAddress and port for the Tunnel.
*
*/
void SetDestination(const uint64_t nodeId, const IPAddress ipAddr,
const uint16_t servicePort = WEAVE_PORT);
/**
* Set the Tunneling device role(BorderGateway, StandaloneDevice, MobileDevice) for the Tunnel.
*
*/
void SetTunnelingDeviceRole(const Role role);
/**
* Get the TunnelAgent state.
*
*/
AgentState GetWeaveTunnelAgentState(void);
#if WEAVE_CONFIG_TUNNEL_TCP_USER_TIMEOUT_SUPPORTED
/**
* Configure the TCP user timeout option on the primary tunnel connection.
*/
WEAVE_ERROR ConfigurePrimaryTunnelTimeout(uint16_t maxTimeoutSecs);
#endif // WEAVE_CONFIG_TUNNEL_TCP_USER_TIMEOUT_SUPPORTED
#if WEAVE_CONFIG_TUNNEL_TCP_KEEPALIVE_SUPPORTED
/**
* Configure and enable the TCP keepalive option on the primary
* tunnel connection.
*/
WEAVE_ERROR ConfigureAndEnablePrimaryTunnelTCPKeepAlive(uint16_t keepAliveIntervalSecs,
uint16_t maxNumProbes);
#endif // WEAVE_CONFIG_TUNNEL_TCP_KEEPALIVE_SUPPORTED
#if WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
/**
* Configure the Primary Tunnel Liveness interval.
*/
void ConfigurePrimaryTunnelLivenessInterval(uint16_t livenessIntervalSecs);
#endif // WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
/**
* Check if the primary tunnel is enabled.
*/
bool IsPrimaryTunnelEnabled(void) const;
/**
* Enable Primary Tunnel.
*/
void EnablePrimaryTunnel(void);
/**
* Disable Primary Tunnel.
*/
void DisablePrimaryTunnel(void);
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
/**
* Check if the backup tunnel is enabled.
*/
bool IsBackupTunnelEnabled(void) const;
/**
* Enable Backup Tunnel.
*/
void EnableBackupTunnel(void);
/**
* Disable Backup Tunnel.
*/
void DisableBackupTunnel(void);
/**
* Start Primary Tunnel.
*/
void StartPrimaryTunnel(void);
/**
* Stop Primary Tunnel.
*/
void StopPrimaryTunnel(void);
/**
* Start Backup Tunnel.
*/
void StartBackupTunnel(void);
/**
* Stop Backup Tunnel.
*/
void StopBackupTunnel(void);
#if WEAVE_CONFIG_TUNNEL_TCP_USER_TIMEOUT_SUPPORTED
/**
* Configure the TCP user timeout option on the backup tunnel connection.
*/
WEAVE_ERROR ConfigureBackupTunnelTimeout(uint16_t maxTimeoutSecs);
#endif // WEAVE_CONFIG_TUNNEL_TCP_USER_TIMEOUT_SUPPORTED
#if WEAVE_CONFIG_TUNNEL_TCP_KEEPALIVE_SUPPORTED
/**
* Configure and enable the TCP keepalive option on the backup
* tunnel connection.
*/
WEAVE_ERROR ConfigureAndEnableBackupTunnelTCPKeepAlive(uint16_t keepAliveIntervalSecs,
uint16_t maxNumProbes);
#endif // WEAVE_CONFIG_TUNNEL_TCP_KEEPALIVE_SUPPORTED
#if WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
/**
* Configure the Backup Tunnel Liveness interval.
*/
void ConfigureBackupTunnelLivenessInterval(uint16_t livenessIntervalSecs);
#endif // WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
/**
* Set the primary tunnel interface name
*
*/
void SetPrimaryTunnelInterface(const char *primaryIntfName);
/**
* Set the backup tunnel interface name
*
*/
void SetBackupTunnelInterface(const char *backupIntfName);
/**
* Set the primary tunnel interface type
*
*/
void SetPrimaryTunnelInterfaceType(const SrcInterfaceType primaryIntfType);
/**
* Set the backup tunnel interface type
*
*/
void SetBackupTunnelInterfaceType(const SrcInterfaceType backupIntfType);
#endif // WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
/**
* Shutdown the Tunnel Agent. This tears down connection to the Service and closes the TunEndPoint
* interface after removing addresses and routes associated with the tunnel interface.
*/
WEAVE_ERROR Shutdown(void);
/**
* Start the Service Tunnel. This enables the tunnel and tries to establish a connection
* to the Service.
*/
WEAVE_ERROR StartServiceTunnel(void);
/**
* Start the Service Tunnel. This enables the tunnel and tries to establish a connection
* to the Service.
*/
WEAVE_ERROR StartServiceTunnel(uint64_t dstNodeId,
IPAddress dstIPAddr,
WeaveAuthMode authMode);
/**
* Close the Tunnel connection to the Service.
*/
void StopServiceTunnel(void);
/**
* Close the Tunnel connection to the Service.
*/
void StopServiceTunnel(WEAVE_ERROR err);
#if WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
/**
* Get the WeaveTunnel statistics counters.
*
* @param[out] tunnelStats A reference to the WeaveTunnelStatistics structure.
*
* @return WEAVE_ERROR Weave error encountered when getting tunnel statistics.
*/
WEAVE_ERROR GetWeaveTunnelStatistics(WeaveTunnelStatistics &tunnelStats);
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
/**
* Function pointer to handler set by a higher layer to act upon various notifications related to
* the tunnel to the Service.
*
* @param[in] reason The reason for the status notification to the application.
*
* @param[in] err Weave error encountered, if any
*
* @param[in] appCtxt A pointer to an application context object
*
* @return void.
*/
typedef void (*OnServiceTunnelStatusNotifyFunct)(WeaveTunnelConnectionMgr::TunnelConnNotifyReasons reason,
WEAVE_ERROR err, void *appCtxt);
/**
* Function pointer to handler set by a higher layer to act upon various notifications related to
* the tunnel to the Service.
*
*/
OnServiceTunnelStatusNotifyFunct OnServiceTunStatusNotify;
/**
* Function pointer to handler set by a higher layer when a Tunnel Reconnect is received from the Service
*
* @param[in] tunType The tunnel type, Primary or Backup.
*
* @param[in] reconnectHost The hostname provided by Service to reconnect to.
*
* @param[in] reconnectPort The destination port provided by Service to reconnect to.
*
* @param[in] appCtxt A pointer to an application context object
*
* @return void.
*/
typedef void (*OnServiceTunnelReconnectNotifyFunct)(TunnelType tunType,
const char *reconnectHost,
const uint16_t reconnectPort,
void *appCtxt);
OnServiceTunnelReconnectNotifyFunct OnServiceTunReconnectNotify;
#if WEAVE_CONFIG_TUNNEL_ENABLE_TRANSIT_CALLBACK
/**
* Function pointer to handler set by a higher layer to decode and log contents of IP packets.
*
* @param[in] pkt A const reference to an IP packet buffer.
*
* @param[in] direction The direction of the tunneled packet(inbound or outbound).
*
* @param[in] type The type of the Tunnel.
*
* @param[out] toDrop indicates whether the packet needs to be dropped based on some application policy.
*
* @return void.
*/
typedef void (*OnPacketTransitFunct)(const PacketBuffer &pkt,
nl::Weave::Profiles::WeaveTunnel::TunnelPktDirection direction,
nl::Weave::Profiles::WeaveTunnel::TunnelType type, bool &toDrop);
OnPacketTransitFunct OnTunneledPacketTransit;
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_TRANSIT_CALLBACK
/**
* Handler to receive IPv6 packets from the Tunnel EndPoint interface and forward, either to the Service
* via the Service TCP connection after encapsulating IPv6 packet inside the tunnel header or to the Mobile
* client over a shortcut tunnel. If the Service connection is not yet up, the message is queued until the
* connection is set up. For tunneling to the Mobile client device, the nexthop neighbor table is referenced.
*/
static void RecvdFromTunnelEndPoint(TunEndPoint *tunEP, PacketBuffer *message);
/**
* Handler to receive tunneled IPv6 packets over the shortcut UDP tunnel between the border gateway and the mobile
* device and forward to the Tunnel EndPoint interface after decapsulating the raw IPv6 packet from inside the
* tunnel header.
*/
static void RecvdFromShortcutUDPTunnel (WeaveMessageLayer *msgLayer, PacketBuffer *message);
/**
* Get the WeaveTunnelAgentState name
*
*/
const char *GetAgentStateName(const AgentState state);
/**
* Get the system time in milliseconds
*
*/
uint64_t GetTimeMsec(void);
private:
// Node Id of the Service endpoint
uint64_t mPeerNodeId;
// IP address of the Service endpoint
IPAddress mServiceAddress;
// Port of the Service endpoint
uint16_t mServicePort;
// Authentication mode to be used
WeaveAuthMode mAuthMode;
// Queued messages for Service; pending until connection established.
PacketBuffer *queuedMsgs[WEAVE_CONFIG_TUNNELING_MAX_NUM_PACKETS_QUEUED];
int qFront, qRear;
// Role; Border gateway or Mobile device
uint8_t mRole;
// Flag for enabling/disabling specific Tunnel
uint8_t mTunnelFlags;
InetLayer *mInet; // Associated InetLayer object
#if !WEAVE_SYSTEM_CONFIG_USE_LWIP
// Interface name of TunEndPoint
char mIntfName[TUN_INTF_NAME_MAX_LEN];
#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
TunEndPoint *mTunEP;
// Handle to the WeaveExchangeManager object.
WeaveExchangeManager *mExchangeMgr;
// Weave Tunnel Connection Manager object for the Primary tunnel
WeaveTunnelConnectionMgr mPrimaryTunConnMgr;
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
// Weave Tunnel Connection Manager object for the Backup tunnel
WeaveTunnelConnectionMgr mBackupTunConnMgr;
#endif
#if WEAVE_CONFIG_TUNNEL_SHORTCUT_SUPPORTED
// Weave Tunnel Control for Tunnel shortcut
WeaveTunnelControl mTunShortcutControl;
#endif
// WeaveTunnelAgent state
AgentState mTunAgentState;
// Application context
void *mAppContext;
#if WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
WeaveTunnelStatistics mWeaveTunnelStats;
void UpdateOutboundMessageStatistics(const TunnelType tunType, const uint64_t msgLen);
void UpdateTunnelDownStatistics(const TunnelType tunType, const WEAVE_ERROR conErr);
WeaveTunnelCommonStatistics *GetCommonTunnelStatistics(const TunnelType tunType);
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_STATISTICS
void SetState(AgentState toState);
// TunEndPoint management functions
WEAVE_ERROR CreateTunEndPoint(void);
WEAVE_ERROR SetupTunEndPoint(void);
WEAVE_ERROR TeardownTunEndPoint(void);
// Tunnel management and maintenance functions
WEAVE_ERROR ConfigureAndInit (InetLayer *inet, WeaveExchangeManager *exchMgr,
uint64_t dstNodeId, IPAddress dstIPAddr, WeaveAuthMode authMode,
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
WeaveServiceManager *svcMgr,
#endif
const char *intfName, uint8_t role, void *appContext);
// Message encapsulating/decapsulating functions for sending between Tunnel and other interfaces
WEAVE_ERROR AddTunnelHdrToMsg(PacketBuffer *msg);
WEAVE_ERROR HandleSendingToService(PacketBuffer *msg);
WEAVE_ERROR HandleTunneledReceive(PacketBuffer *msg, TunnelType tunType);
/// Decide based on lookup of nexthop table and send locally
/// via UDP tunnel or remotely via Service TCP connection.
WEAVE_ERROR DecideAndSendShortcutOrRemoteTunnel(uint64_t nodeId, PacketBuffer *msg);
void PopulateTunnelMsgHeader(WeaveMessageInfo *msgInfo, const WeaveTunnelConnectionMgr *connMgr);
void ParseDestinationIPAddress(const PacketBuffer &inMsg, IPAddress &outDest);
WEAVE_ERROR SendMessageUponPktTransitAnalysis(const WeaveTunnelConnectionMgr *connMgr,
TunnelPktDirection pktDir,
TunnelType tunType,
WeaveMessageInfo *msgInfo,
PacketBuffer *msg,
bool &dropPacket);
static void ServiceMgrStatusHandler(void* appState, WEAVE_ERROR err, StatusReport *report);
// Service queue management functions
void SendQueuedMessages(const WeaveTunnelConnectionMgr *connMgr);
WEAVE_ERROR EnQueuePacket(PacketBuffer *pkt);
PacketBuffer *DeQueuePacket(void);
void DumpQueuedMessages(void);
// Tunnel Control post-processing functions
void WeaveTunnelConnectionUp(const WeaveMessageInfo *msgInfo,
const WeaveTunnelConnectionMgr *connMgr,
const bool isRoutingRestricted);
void WeaveTunnelConnectionDown(const WeaveTunnelConnectionMgr *connMgr, WEAVE_ERROR conErr);
void WeaveTunnelServiceReconnectRequested(const WeaveTunnelConnectionMgr *connMgr,
const char *redirectHost, const uint16_t redirectPort);
void WeaveTunnelDownNotifyAndSetState(WEAVE_ERROR conErr);
void WeaveTunnelUpNotifyAndSetState(AgentState state,
Platform::TunnelAvailabilityMode tunMode,
WeaveTunnelConnectionMgr::TunnelConnNotifyReasons notifyReason,
WeaveTunnelConnectionMgr *connMgr,
const bool isRoutingRestricted);
void RemovePlatformTunnelRoute(void);
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
void WeaveTunnelModeChangeNotifyAndSetState(AgentState state,
Platform::TunnelAvailabilityMode tunMode,
WeaveTunnelConnectionMgr::TunnelConnNotifyReasons notifyReason,
WEAVE_ERROR conErr);
#endif // WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
void WeaveTunnelConnectionErrorNotify(const WeaveTunnelConnectionMgr *connMgr, WEAVE_ERROR conErr);
#if WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
void RestartTunnelLivenessTimer(TunnelType tunType);
void NotifyTunnelLiveness(TunnelType tunType, WEAVE_ERROR err);
#endif // WEAVE_CONFIG_TUNNEL_LIVENESS_SUPPORTED
};
} // namespace WeaveTunnel
} // namespace Profiles
} // namespace Weave
} // namespace nl
#endif // WEAVE_CONFIG_ENABLE_TUNNELING
#endif// _WEAVE_TUNNEL_AGENT_H_