美文网首页
NDN新增tag的方案

NDN新增tag的方案

作者: SunnyQjm | 来源:发表于2020-04-19 19:59 被阅读0次

    本文档展示如何修改ndn-cxx和NFD的源码,添加一个值基本类型的Tag,下面的过程将展示添加一个值为uint64_t类型的Tag SrcAddress

    添加Tag的含义

    NDNLPv2协议中定义了LpPacket,具体的格式如下:

    LpPacket = LP-PACKET-TYPE TLV-LENGTH
                 *LpHeaderField
                 [Fragment]
    
    LpHeaderField = Sequence
    
    Sequence = SEQUENCE-TYPE TLV-LENGTH 8OCTET
    
    Fragment = FRAGMENT-TYPE TLV-LENGTH 1*OCTET
    
    • 其中Fragment放置的可以是一个NDN报的分片,或者是一个完整的NDN包(NDN包足够小,不需要分片的情况);
    • *LpHeaderField就是一系列的LpPacket的Header,类似一个变长的数组,所以可以自己定义新的LpHeader;
    • 所以添加一个新的Tag实际上就是添加一个新的LpHeader。

    修改ndn-cxx

    • 修改ndn-cxx/lp/tlv.hpp,为将要添加的新Tag分配一个新的TLV类型

      enum {
          LpPacket = 100,
          Fragment = 80,
          Sequence = 81,
          FragIndex = 82,
          FragCount = 83,
          PitToken = 98,
          Nack = 800,
          NackReason = 801,
          NextHopFaceId = 816,
          IncomingFaceId = 817,
          CachePolicy = 820,
          CachePolicyType = 821,
          CongestionMark = 832,
          Ack = 836,
          TxSequence = 840,
          NonDiscovery = 844,
          PrefixAnnouncement = 848,
          ///////////////////////////////////////////////////// add by qjm, for add new tag
          SrcAddress = 852
          /////////////////////////////////////////////////////
      };
      

      如上所示,我们给新添加的Tag分配了一个TLV type,这个type是唯一标识一个TLV的。并且该值的分配也是需要遵循一定准则的,具体的分配规则可以参考:https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2

      Reserved Blocks

      Two blocks of TLV-TYPEs have been reserved by link protocols:

      • [80, 100]: 1-octet encoding
      • [800, 1000]: 3-octet encoding

      TLV-TYPE numbers for LpHeaderField SHOULD be assigned according to the following rules:

      1. if the field can be safely ignored by a receiver that doesn't understand the field, pick an unused number in the range [800, 959] whose two least significant bits are 00.
      2. if the field would occur frequently, pick an unused number in the range [81, 99].
      3. otherwise, pick an unused number in the range [800, 959] whose two least significant bits are效果 01.

      Note: number assignment for a TLV-TYPE nested within a LpHeaderField is not restricted by the above rules.

    • 修改ndn-cxx/lp/tags.hpp,定义一个新的Tag:

      /////////////////////////////////////////////////// add by qjm, for add new tag
      typedef SimpleTag<uint64_t, 16> SrcAddressTag;
      ///////////////////////////////////////////////////
      
    • 修改ndn-cxx/lp/fields.hpp,添加新Tag对应的Field:

      ////////////////////////////////////////////////////// add by qjm, for add new tag
      typedef FieldDecl<field_location_tags::Header,
              uint64_t, tlv::SrcAddress> SrcAddressField;
      BOOST_CONCEPT_ASSERT((Field<SrcAddressField>));
      //////////////////////////////////////////////////////
      
      /** \brief Set of all field declarations.
      */
      typedef boost
      ::mpl::set<
              FragmentField,
              SequenceField,
              FragIndexField,
              FragCountField,
              PitTokenField,
              NackField,
              NextHopFaceIdField,
              IncomingFaceIdField,
              CachePolicyField,
              CongestionMarkField,
              AckField,
              TxSequenceField,
              NonDiscoveryField,
              PrefixAnnouncementField,
              /////////////////////////////////////////////// add by qjm, for add new tag
              SrcAddressField
              ///////////////////////////////////////////////
      > FieldSet;
      
    • 修改ndn-cxx/face.cpp => extractLpLocalFields

      template<typename NetPkt>
      static void
      extractLpLocalFields(NetPkt &netPacket, const lp::Packet &lpPacket) {
          addTagFromField<lp::IncomingFaceIdTag, lp::IncomingFaceIdField>(netPacket, lpPacket);
          addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(netPacket, lpPacket);
      
          ////////////////////////////////////////////////////// add by qjm, for add new tag
          addTagFromField<lp::SrcAddressTag, lp::SrcAddressField>(netPacket, lpPacket);
          //////////////////////////////////////////////////////
      }
      

      上面的静态函数是在一个Face从Transport接收到一个Element,进行解析时调用的,功能是 将收到的LpPacket中的LpHeaderField提取,并保存到指定包的Tag列表当中

    • 如果插入的Tag要在Interest包中生效,则需要修改ndn-cxx/impl/face-impl.hpp => asyncExpressInterest

      void
      asyncExpressInterest(RecordId id, shared_ptr<const Interest> interest,
                           const DataCallback &afterSatisfied,
                           const NackCallback &afterNacked,
                           const TimeoutCallback &afterTimeout) {
          NDN_LOG_DEBUG("<I " << *interest);
          this->ensureConnected(true);
      
          const Interest &interest2 = *interest;
          auto &entry = m_pendingInterestTable.put(id, std::move(interest), afterSatisfied, afterNacked,afterTimeout, ref(m_scheduler));
      
          lp::Packet lpPacket;
      
          addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest2);
          addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest2);
      
          ////////////////////////////////////////////////////// add by qjm, for add new tag
          addFieldFromTag<lp::SrcAddressField, lp::SrcAddressTag>(lpPacket, interest2);
          //////////////////////////////////////////////////////
      
          entry.recordForwarding();
          m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest2.wireEncode(),
                                                  'I', interest2.getName()));
          dispatchInterest(entry, interest2);
      }
      

      上面新添的代码的功能是将一个要发送的包(Interest、Data等继承自TagHost)中的Tag提取处理出来,并作为一个LpHeaderField写入新构造的lpPacket当中。

    • 如果插入的Tag要在Data包中生效,则需要修改ndn-cxx/impl/face-impl.hpp => asyncPutData

      void
      asyncPutData(const Data &data) {
          NDN_LOG_DEBUG("<D " << data.getName());
          bool shouldSendToForwarder = satisfyPendingInterests(data);
          if (!shouldSendToForwarder) {
              return;
          }
      
          this->ensureConnected(true);
      
          lp::Packet lpPacket;
          addFieldFromTag<lp::CachePolicyField, lp::CachePolicyTag>(lpPacket, data);
          addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
          
         /////////////////////////////////////////////////// add by qjm, for add new tag
          addFieldFromTag<lp::SrcAddressField, lp::SrcAddressTag>(lpPacket, data);
          //////////////////////////////////////////////////
      
          m_face.m_transport->send(finishEncoding(std::move(lpPacket), data.wireEncode(),
                                                  'D', data.getName()));
      }
      

      上面新添的代码的功能是将一个要发送的包(Interest、Data等继承自TagHost)中的Tag提取处理出来,并作为一个LpHeaderField写入新构造的lpPacket当中。

    修改NFD

    NFD中需要修改daemon/face/generic-link-service.cpp中的两处代码:

    • GenericLinkService::decodeInterest

      void
      GenericLinkService::decodeInterest(const Block &netPkt, const lp::Packet &firstPkt,
                                         const EndpointId &endpointId) {
          .....
      
          /////////////////////////////////////////////// add by qjm, for add srcAddress Tag
          if (firstPkt.has<lp::SrcAddressField>()) {
              interest->setTag(make_shared<lp::SrcAddressTag>(firstPkt.get<lp::SrcAddressField>()));
          }
          ///////////////////////////////////////////////
      
          this->receiveInterest(*interest, endpointId);
      }
      

      上面的代码在GenericLinkService解析Interest的时候,提取对应LpPacket中的Field,写入Interest的tags列表当中。

      ps: 由于此处演示的是添加一个Tag,只对于Interest生效,所以需要修改这个函数,如果要对Data包或者Nack等包生效,类比上述代码,对GenericLinkService::decodeDataGenericLinkService::decodeNack之类的进行修改即可

    • GenericLinkService::encodeLpFields

      void
      GenericLinkService::encodeLpFields(const ndn::PacketBase &netPkt, lp::Packet &lpPacket) {
         .....
      
          /////////////////////////////////////////////// add by qjm, for add srcAddress Tag
          auto srcAddressTag = netPkt.getTag<lp::SrcAddressTag>();
          if (srcAddressTag != nullptr) {
              lpPacket.add<lp::SrcAddressField>(*srcAddressTag);
          }
          ///////////////////////////////////////////////
      
          auto pitToken = netPkt.getTag<lp::PitToken>();
          if (pitToken != nullptr) {
              lpPacket.add<lp::PitTokenField>(*pitToken);
          }
      }
      

      上面新添的代码会在发送一个包的时候调用,目的是将Tag提取出来,座位一个LpHeaderField 添加到LpPacket中。

    添加成功后的效果

    Tag添加成功效果

    相关文章

      网友评论

          本文标题:NDN新增tag的方案

          本文链接:https://www.haomeiwen.com/subject/mlzbbhtx.html