Last active
October 11, 2015 15:34
-
-
Save yoursunny/22a7d53711b4e9bc198a to your computer and use it in GitHub Desktop.
NFD Face System design for LinkService http://redmine.named-data.net/issues/2222 and permanent face http://redmine.named-data.net/issues/2491
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Face design | |
// This design incorporates: | |
// Link Services http://redmine.named-data.net/issues/2222 | |
// Permanent Face http://redmine.named-data.net/issues/2491 | |
// -------- Face, Socket, LinkService -------- | |
namespace nfd { | |
namespace face { | |
typedef uint64_t FaceId; | |
enum class FaceState { | |
NONE, | |
DOWN, | |
UP | |
}; | |
// may need more states when we have tunnel authentication (eg. UNAUTHENTICATED) | |
class Face : noncopyable | |
{ | |
public: | |
Face(LinkService& service, Socket& socket); | |
public: // upper interface connected to forwarding | |
void | |
sendInterest(const Interest& interest); | |
void | |
sendData(const Data& interest); | |
void | |
sendNack(const Nack& interest); | |
Signal<LinkService, Interest>& afterReceiveInterest; | |
Signal<LinkService, Data>& afterReceiveData; | |
Signal<LinkService, Nack>& afterReceiveNack; | |
public: // static properties | |
FaceId | |
getId() const; // from Face | |
FaceUri | |
getLocalUri() const; // from Socket | |
FaceUri | |
getRemoteUri() const; // from Socket | |
FacePersistency | |
getPersistency() const; // from Socket | |
LinkType // point-to-point|multi-access | |
getLinkType() const; // from Socket | |
public: // dynamic properties | |
FaceState | |
getState() const; // from Socket | |
Signal<Link, FaceState/*old*/, FaceState/*new*/>& afterStateChange; | |
FaceCounters | |
getCounters() const; // network layer packet counters from LinkService, link layer packet and byte counters from Socket | |
}; | |
class Socket | |
{ | |
public: | |
struct Packet | |
{ | |
Block packet; | |
NetworkAddress localAddr; | |
NetworkAddress remoteAddr; | |
} | |
public: // upper interface | |
void | |
send(const Packet& packet); // increment counter and call .doSend | |
Signal<Link, Packet> afterReceive; | |
private: // upper interface to be overridden by subclass | |
virtual void | |
doSend(const Packet& packet) = 0; | |
protected: // upper interface to be invoked by subclass | |
void | |
receive(const Packet& packet); // increment counter and signal afterReceive | |
public: // static properties | |
FaceUri | |
getLocalUri() const; | |
FaceUri | |
getRemoteUri() const; | |
FacePersistency | |
getPersistency() const; | |
// If persistency==PERMANENT, Socket is responsible for recovery. | |
// But tunnel authentication should be done by another component through a signal. | |
LinkType | |
getLinkType() const; | |
public: // dynamic properties | |
FaceState | |
getState() const; | |
Signal<Link, FaceState/*old*/, FaceState/*new*/> afterStateChange; | |
// This should be UP/DOWN only. | |
// Tunnel authentication's UNAUTHENTICATED state should come from LinkService or mgmt. | |
// By that time, we may define a separate enum as SocketState{DOWN,UP}. | |
LinkCounters | |
getCounters() const; // link layer packet and byte counters | |
protected: | |
void | |
changeState(FaceState newState); // UP/DOWN only | |
}; | |
class LinkService | |
{ | |
public: | |
void | |
setSocket(Socket& link); | |
public: // upper interface connected to forwarding | |
void | |
sendInterest(const Interest& interest); // increment counter and call .doSendInterest | |
void | |
sendData(const Data& interest); // increment counter and call .doSendData | |
void | |
sendNack(const Nack& interest); // increment counter and call .doSendNack | |
Signal<LinkService, Interest> afterReceiveInterest; | |
Signal<LinkService, Data> afterReceiveData; | |
Signal<LinkService, Nack> afterReceiveNack; | |
private: // upper interface to be overridden in subclass | |
virtual void | |
doSendInterest(const Interest& interest) = 0; | |
virtual void | |
doSendData(const Data& interest) = 0; | |
virtual void | |
doSendNack(const Nack& interest) = 0; | |
protected: // upper interface to be invoked in subclass | |
void | |
receiveInterest(const Interest& interest); // increment counter and signal afterReceiveInterest | |
void | |
receiveData(const Data& data); // increment counter and signal afterReceiveData | |
void | |
receiveNack(const Nack& nack); // increment counter and signal afterReceiveNack | |
protected: // lower interface | |
bool | |
sendPacket(const Socket::Packet& packet); | |
private: // lower interface | |
virtual void | |
receivePacket(const Socket::Packet& packet) = 0; | |
public: // dynamic properties | |
NetCounters | |
getCounters(); // network layer packet counters | |
}; | |
} // namespace face | |
} // namespace nfd | |
// -------- generic LinkService -------- | |
namespace nfd { | |
namespace face { | |
class GenericLinkService : public LinkService | |
{ | |
public: | |
class Options | |
{ | |
bool enableFragmentation; | |
bool enableReassembly; | |
// send path and receive path should have separate options if it makes sense | |
time::nanoseconds reassemblyTimeout; | |
// (other options can be added when necessary) | |
bool allowLocalFields; | |
// enableLocalFields enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy. | |
// Nack is always enabled, because there's no harm keeping it enabled. | |
// When decoding, implementation should ensure a field is attached on a correct network layer packet type, | |
// especially when protocol defines "packet MUST be dropped" (eg. Nack is only allowed on an Interest). | |
}; | |
explicit | |
GenericLinkService(const Options& options); | |
const Options& | |
getOptions() const; | |
void | |
setOptions(const Options& options); | |
private: // send path entrypoint | |
virtual void | |
doSendInterest(const Interest& interest) override; | |
virtual void | |
doSendData(const Data& interest) override; | |
virtual void | |
doSendNack(const Nack& interest) override; | |
private: // receive path entrypoint | |
virtual void | |
receivePacket(const Socket::Packet& packet) override; | |
}; | |
// Apart from packet encoding/decoding (which includes Nack, IncomingFaceId, NextHopFaceId, CachePolicy), | |
// we only have fragmentation+reassembly service for now. | |
// So we only need a few classes for fragmentation and reassembly (similar to NDNLPv1 implementation), | |
// plus a separate step for assigning sequence numbers. | |
// Unlike NDNLPv1 implementation, sequence number allocation should happen after fragmentation; | |
// which is necessary to accomodate transmitting IDLE packets from other services. | |
// Each of doSendX methods should do encoding, invoke fragmentation, invoke seq allocation, and invoke .sendPacket to pass down LpPacket; | |
// the latter 3 steps should be done in a common helper function; | |
// in case fragmentation is disabled, that helper function can invoke .sendPacket straight. | |
// receivePacket should call reassembly, do decoding, and invoke .receiveX to pass up network layer packet; | |
// in case reassembly is disabled, this method can skip reassembly step. | |
} // namespace face | |
} // namespace nfd |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment