NFD-face系统
Face接口:广义网络接口,可以理解为:
- 物理链路的接口;
- 与NFD远程节点的通信信道(接口);
- 本地节点与本地应用程序的通信信道(接口)。
nfd的Face由链路服务和传输两个模块组成:linkservice
和transport
Face在整个ndnSIM中定义主要涉及到src/ndnSIM/NFD/daemon/face/face.cpp
;src/ndnSIM/ndn-cxx/ndn-cxx/face.cpp
;通过src/ndnSIM/NFD/daemon/face/internal-face.cpp
将两者联系起来
ndn Face的创建和调用:以ndn-simple为例:
创建:ndn-simple中创建StackHelper时,通过调用其构造函数中的回调函数中实现。
1 | //ndn-simple.cpp |
调用:ndn face
consumer到forwarder之间通过face的Linkservice实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14//ndn-comsumer的send packet
m_appLink->onReceiveInterest(*interest);
//AppLinkService::onReceiveInterest
this->receiveInterest(interest); //实际上调用的linkservice的receiveInterest
//LinkService::receiveInterest
afterReceiveInterest(interest); //触发了信号signal::Signal<LinkService, Interest> afterReceiveInterest;(定义在hpp中)
//face的构造函数中将service的信号传给face的信号
afterReceiveInterest(service->afterReceiveInterest)
//forward的构造函数中,face的信号触发了forwarder的startProcessInterest
m_faceTable.afterAdd.connect([this] (Face& face) {
face.afterReceiveInterest.connect(
[this, &face] (const Interest& interest) {
this->startProcessInterest(face, interest); //通过LinkService::receiveInterest,进一步触发Forwarder::startProcessInterest
});forwarder处理完后向下层转发时使用。
1 | //Forwarder::onOutgoingInterest |
cxx Face的创建:以ndn-simple为例:
1 | //ndn-simple |
Internal-face:连接起了ndnsim中的face和NFD中的face
1 | //internal-face.hpp |
nfd中的face:
1 | Face::Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport) //构造函数 |
主要功能:给linkservice和tranport派活,起到一个组织管理的角色。
ndncxx中的face:
类似与一个client端的face,并且建立了和face之间的通道,主要用作和nfd的face之间传递管理信息。
L3Protocol:将cxx中的face和ndn中的face联系起来。和face相关的主要包括faceTable,faceSystem,两组internal-face。(internalFace和internalClientFace;internalFaceForInjects和internalClientFaceForInjects)
Facetable:管理face的一个map,键存的是faceID,值存的是整个Face类
Facesystem:包括facetable和NetworkMonitor,NetworkMonitor感觉是管理face是否确实接入到了网络中,如果确实接入了,就会触发一些信号。
internalFaceForInjects和internalClientFaceForInjects用于建立一组内部的face获取管理信息。其基本流程为:
1 | //client face发送请求兴趣包,ndn-fib-helper和ndn=stratege-choice-helper用到了injectInterest函数,实际上是交给forwarder处理的 |
internalFace和internalClientFace用于创建Dispatcher,用于常见的兴趣包,数据包处理。Dispatcher用于和各种manager进行交互,这个不需要经过forwarder。
Dispatcher的几种机制:
- Control Command:所有改变NFD状态的管理操作都需要使用控制命令
- Notification streams:是NFD管理协议的一种机制,用于监视NFD状态
1 | m_impl->m_dispatcher = make_unique<::ndn::mgmt::Dispatcher>(*m_impl->m_internalClientFace, StackHelper::getKeyChain()); |
ManagerBase是所有manager的基类,face-manager,cs-manager,fib-manager等。此类包含Dispatcher和CommandValidator。
manager:管理器总是由一系列处理程序组成,每个处理程序负责处理control command请求兴趣包,主要包括:face,fib,strategy-choice等
dispatcher:管理器利用ndn :: Dispatcher作为抽象处理常见兴趣包/数据包
1.管理器向调度程序注册一个处理程序,该部分由管理器的名称和动词组成。 registerCommandHandler(const std::string& verb,const ControlCommandHandler& handler);
2.在所有管理器都注册了处理程序之后,调度程序使用该部分名称加上每个注册的顶级前缀(例如/ localhost / nfd)创建完整的前缀
3.然后为它们设置兴趣包过滤器
4.兴趣包经过过滤后,定向到具体的管理器处理程序
(更多相关的内容可以参考NFD开发手册管理模块)
Control Command 控制命令
请求的签名兴趣包格式:/
- prefix是NFD管理前缀。除非另有说明,否则所有命令都使用/ localhost / nfd前缀
- management-module是需要将命令分派到的管理模块的名称
- command-verb是要执行的操作
- control-parameters是一个包含在NameComponent中的ControlParameters TLV元素
- command-interest-components是命令兴趣包规范定义的四个附加组件
Notification streams:
- Notification streams在特定名称前缀(/localhost/nfd前缀)下发布
- Notification是此名称前缀下的数据包,带有序列号
- 序列号组件是NameComponentWithMarkerAndNumber,与NDN命名规则一样。该组件0xFE标记开头,后跟nonNegativeInteger
- 同一流中的通知的序列号应该是连续的并且在增加
- 每个通知仅限一个数据包
1 | //manager-base.cpp manager向Dispatcher注册通知流 |
定义face一个是为了能自己添加策略,另外一个是能通过trace统计输出。NLSR每个对象都对应了一个face。
ndn-cxx的face和nfd的face:
重新梳理了一下ndn-cxx的face和nfd的face的联系,以hello-protocal来说明的使用来说明其关系。
ndn-cxx的face功能主要在于联系上层的应用和转发层forwarder。HelloBroadcastProtocol::expressInterest
调用了cxx的face发送兴趣包,在face-impl
中对兴趣包编码并通过internal-face
发送,实际调用的是internal-face-client
的send
,其会调用internal-face-forwarder
的receive
,其进一步调用linkservice对兴趣包解码,然后触发afterreceiveinterest
,afterreceiveinterest
触发NFD转发程序,再根据兴趣包的ingress和ongress决定如何将兴趣包转发。
对于常规的NDN的管理信息,其可能会发送到forwarder中发现FIB中没有下一跳,于是就不转发了。而对于Hello包来说,到forwarder中发现FIB中有下一跳,就会将其转发。