Skip to content

Commit 82d8ed0

Browse files
jaczhiPesa
authored andcommitted
mgmt: support rib/announce control command
This commit adds support for a new control command type, RibAnnounceCommand. A new command format class is also added, ApplicationParametersCommandFormat, to support encoding the request information in the ApplicationParameters element of the interest instead of using ControlParameters. Refs: #4650 Change-Id: I351d3852062a80349fb67d7f18db4c883551835c
1 parent e595c76 commit 82d8ed0

File tree

5 files changed

+193
-4
lines changed

5 files changed

+193
-4
lines changed

ndn-cxx/mgmt/nfd/control-command.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,42 @@ RibUnregisterCommand::validateResponseImpl(const ControlParameters& parameters)
347347
}
348348
}
349349

350+
void
351+
RibAnnounceParameters::wireDecode(const Block& wire)
352+
{
353+
wire.parse();
354+
auto it = wire.find(tlv::Data);
355+
if (it == wire.elements_end()) {
356+
NDN_THROW(Error("Missing prefix announcement parameter"));
357+
}
358+
m_prefixAnn = PrefixAnnouncement(Data(*it));
359+
}
360+
361+
Block
362+
RibAnnounceParameters::wireEncode() const
363+
{
364+
if (!m_prefixAnn.getData()) {
365+
NDN_THROW(Error("Prefix announcement must be signed"));
366+
}
367+
return m_prefixAnn.getData()->wireEncode();
368+
}
369+
370+
const RibAnnounceCommand::RequestFormat RibAnnounceCommand::s_requestFormat;
371+
const RibAnnounceCommand::ResponseFormat RibAnnounceCommand::s_responseFormat =
372+
RibRegisterCommand::s_responseFormat;
373+
374+
void
375+
RibAnnounceCommand::validateRequestImpl(const RibAnnounceParameters& parameters)
376+
{
377+
if (!parameters.getPrefixAnnouncement().getData()) {
378+
NDN_THROW(ArgumentError("Prefix announcement must be signed"));
379+
}
380+
}
381+
382+
void
383+
RibAnnounceCommand::validateResponseImpl(const ControlParameters& parameters)
384+
{
385+
RibRegisterCommand::validateResponseImpl(parameters);
386+
}
387+
350388
} // namespace ndn::nfd

ndn-cxx/mgmt/nfd/control-command.hpp

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "ndn-cxx/interest.hpp"
2626
#include "ndn-cxx/mgmt/nfd/control-parameters.hpp"
27+
#include "ndn-cxx/prefix-announcement.hpp"
2728

2829
#include <bitset>
2930

@@ -101,11 +102,54 @@ class ControlParametersCommandFormat
101102
};
102103

103104

105+
/**
106+
* \ingroup management
107+
* \brief Implements decoding, encoding, and validation of control command parameters carried
108+
* in the ApplicationParameters of the request (Interest packet).
109+
* \note This format is applicable to control command requests only.
110+
*/
111+
template<typename PT>
112+
class ApplicationParametersCommandFormat
113+
{
114+
public:
115+
using ParametersType = PT;
116+
117+
/**
118+
* \brief Does nothing.
119+
*/
120+
void
121+
validate(const ParametersType&) const
122+
{
123+
}
124+
125+
/**
126+
* \brief Extract the parameters from the request \p interest.
127+
*/
128+
static shared_ptr<ParametersType>
129+
decode(const Interest& interest, size_t prefixLen = 0)
130+
{
131+
auto params = make_shared<ParametersType>();
132+
params->wireDecode(interest.getApplicationParameters());
133+
return params;
134+
}
135+
136+
/**
137+
* \brief Serialize the parameters into the request \p interest.
138+
*/
139+
static void
140+
encode(Interest& interest, const ParametersType& params)
141+
{
142+
interest.setApplicationParameters(params.wireEncode());
143+
}
144+
};
145+
146+
104147
/**
105148
* \ingroup management
106149
* \brief Base class for all NFD control commands.
107150
* \tparam RequestFormatType A class type that will handle the encoding and validation of the request
108-
* parameters. Only ControlParametersCommandFormat is supported for now.
151+
* parameters. The type can be ApplicationParametersCommandFormat or
152+
* ControlParametersCommandFormat.
109153
* \tparam ResponseFormatType A class type that will handle the encoding and validation of the response
110154
* parameters. Only ControlParametersCommandFormat is supported for now.
111155
* \sa https://redmine.named-data.net/projects/nfd/wiki/ControlCommand
@@ -384,6 +428,7 @@ class StrategyChoiceUnsetCommand : public ControlCommand<StrategyChoiceUnsetComm
384428
class RibRegisterCommand : public ControlCommand<RibRegisterCommand>
385429
{
386430
NDN_CXX_CONTROL_COMMAND("rib", "register");
431+
friend class RibAnnounceCommand;
387432

388433
static void
389434
applyDefaultsToRequestImpl(ControlParameters& parameters);
@@ -409,6 +454,61 @@ class RibUnregisterCommand : public ControlCommand<RibUnregisterCommand>
409454
validateResponseImpl(const ControlParameters& parameters);
410455
};
411456

457+
458+
/**
459+
* \ingroup management
460+
* \brief Request parameters for `rib/announce` command.
461+
*/
462+
class RibAnnounceParameters final : public mgmt::ControlParametersBase
463+
{
464+
public:
465+
class Error : public tlv::Error
466+
{
467+
public:
468+
using tlv::Error::Error;
469+
};
470+
471+
const PrefixAnnouncement&
472+
getPrefixAnnouncement() const
473+
{
474+
return m_prefixAnn;
475+
}
476+
477+
RibAnnounceParameters&
478+
setPrefixAnnouncement(const PrefixAnnouncement& pa)
479+
{
480+
m_prefixAnn = pa;
481+
return *this;
482+
}
483+
484+
void
485+
wireDecode(const Block& wire) final;
486+
487+
Block
488+
wireEncode() const final;
489+
490+
private:
491+
PrefixAnnouncement m_prefixAnn;
492+
};
493+
494+
495+
/**
496+
* \ingroup management
497+
* \brief Represents a `rib/announce` command.
498+
* \sa https://redmine.named-data.net/projects/nfd/wiki/PrefixAnnouncement
499+
*/
500+
class RibAnnounceCommand : public ControlCommand<RibAnnounceCommand,
501+
ApplicationParametersCommandFormat<RibAnnounceParameters>>
502+
{
503+
NDN_CXX_CONTROL_COMMAND("rib", "announce");
504+
505+
static void
506+
validateRequestImpl(const RibAnnounceParameters& parameters);
507+
508+
static void
509+
validateResponseImpl(const ControlParameters& parameters);
510+
};
511+
412512
} // namespace ndn::nfd
413513

414514
#endif // NDN_CXX_MGMT_NFD_CONTROL_COMMAND_HPP

tests/unit/mgmt/dispatcher.t.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ BOOST_AUTO_TEST_CASE(ControlCommandNew,
232232
dispatcher.addControlCommand<nfd::StrategyChoiceUnsetCommand>(makeAcceptAllAuthorization(), handler);
233233
dispatcher.addControlCommand<nfd::RibRegisterCommand>(makeAcceptAllAuthorization(), handler);
234234
dispatcher.addControlCommand<nfd::RibUnregisterCommand>(makeAcceptAllAuthorization(), handler);
235+
dispatcher.addControlCommand<nfd::RibAnnounceCommand>(makeAcceptAllAuthorization(), handler);
235236

236237
BOOST_CHECK_THROW(dispatcher.addControlCommand<nfd::CsConfigCommand>(makeAcceptAllAuthorization(),
237238
[] (auto&&...) {}),

tests/unit/mgmt/nfd/control-command.t.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ndn-cxx/mgmt/nfd/control-command.hpp"
2323

2424
#include "tests/boost-test.hpp"
25+
#include "tests/key-chain-fixture.hpp"
2526

2627
namespace ndn::tests {
2728

@@ -492,6 +493,51 @@ BOOST_AUTO_TEST_CASE(RibUnregister)
492493
BOOST_CHECK_THROW(Command::validateResponse(p2), ArgumentError);
493494
}
494495

496+
BOOST_FIXTURE_TEST_CASE(RibAnnounce, KeyChainFixture)
497+
{
498+
using Command = RibAnnounceCommand;
499+
500+
// Good request
501+
PrefixAnnouncement pa1;
502+
pa1.setAnnouncedName("ndn:/");
503+
pa1.setExpiration(1_min);
504+
pa1.toData(m_keyChain);
505+
RibAnnounceParameters p1;
506+
p1.setPrefixAnnouncement(pa1);
507+
BOOST_CHECK_NO_THROW(Command::validateRequest(p1));
508+
Name n1 = Command::createRequest("/PREFIX", p1).getName();
509+
BOOST_CHECK(Name("ndn:/PREFIX/rib/announce").isPrefixOf(n1));
510+
511+
// Good response
512+
ControlParameters p2;
513+
p2.setName("ndn:/")
514+
.setFaceId(22)
515+
.setOrigin(ndn::nfd::ROUTE_ORIGIN_PREFIXANN)
516+
.setCost(2048)
517+
.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
518+
.setExpirationPeriod(1_min);
519+
BOOST_CHECK_NO_THROW(Command::validateResponse(p2));
520+
521+
// Bad request (PrefixAnnouncement must be signed)
522+
PrefixAnnouncement pa2;
523+
pa2.setAnnouncedName("ndn:/");
524+
pa2.setExpiration(1_min);
525+
RibAnnounceParameters p3;
526+
BOOST_CHECK_THROW(Command::validateRequest(p3), ArgumentError);
527+
p3.setPrefixAnnouncement(pa2);
528+
BOOST_CHECK_THROW(Command::validateRequest(p3), ArgumentError);
529+
530+
// Bad response (FaceId must be valid)
531+
ControlParameters p4;
532+
p4.setName("ndn:/")
533+
.setFaceId(0)
534+
.setOrigin(ndn::nfd::ROUTE_ORIGIN_PREFIXANN)
535+
.setCost(2048)
536+
.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
537+
.setExpirationPeriod(1_min);
538+
BOOST_CHECK_THROW(Command::validateResponse(p4), ArgumentError);
539+
}
540+
495541
BOOST_AUTO_TEST_SUITE_END() // TestControlCommand
496542
BOOST_AUTO_TEST_SUITE_END() // Nfd
497543
BOOST_AUTO_TEST_SUITE_END() // Mgmt

tests/unit/mgmt/nfd/controller.t.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,15 @@ BOOST_AUTO_TEST_CASE(OptionsPrefix)
140140

141141
BOOST_AUTO_TEST_CASE(InvalidRequest)
142142
{
143-
ControlParameters parameters;
144-
parameters.setName("ndn:/should-not-have-this-field");
143+
ControlParameters p1;
144+
p1.setName("/should-not-have-this-field");
145145
// Uri is missing
146+
BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(p1, succeedCallback, commandFailCallback),
147+
ArgumentError);
146148

147-
BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback),
149+
RibAnnounceParameters p2;
150+
// PrefixAnnouncement not signed
151+
BOOST_CHECK_THROW(controller.start<RibAnnounceCommand>(p2, succeedCallback, commandFailCallback),
148152
ArgumentError);
149153
}
150154

0 commit comments

Comments
 (0)