BIND 10 #1224: V4 packet library - basic framework

BIND 10 Development do-not-reply at isc.org
Fri Oct 21 11:49:15 UTC 2011


#1224: V4 packet library - basic framework
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:  stephen
  stephen                            |                Status:  reviewing
                       Type:  task   |             Milestone:  Sprint-
                   Priority:  major  |  DHCP-20111026
                  Component:  dhcp   |            Resolution:
                   Keywords:         |             Sensitive:  0
            Defect Severity:  N/A    |           Sub-Project:  DHCP
Feature Depending on Ticket:         |  Estimated Difficulty:  0
        Add Hours to Ticket:  0      |           Total Hours:  0
                  Internal?:  0      |
-------------------------------------+-------------------------------------
Changes (by tomek):

 * owner:  tomek => stephen


Comment:

 Replying to [comment:6 stephen]:

 Thanks for the review.

 > '''src/lib/dhcp/Makefile.am'''[[BR]]
 > Should add dhcp4.h to libdhcp_la_SOURCES
 Done.

 > '''src/lib/dhcp/dhcp4.h'''[[BR]]
 > Rather than "format kept for easier merge" I think that the real reason
 is that DHCPv4 is still being developed and that this file may change if
 the code is extended.
 >
 > Having said that, the DHCPv4 protocol is fairly fixed, so I think there
 is a very strong case for moving to a C++ paradigm.  In particular,
 defining the different constants as enums would ensure that C++ type
 checking checked that constants were appropriate for the fields.  At this
 stage of the work, it should not be too much of an overhead.
 That is probably true that we won't be doing any merges. Reworked most of
 the header text. I left defines that I don't know about. I don't want to
 guess names for enums just yet. I'll convert them to C++ enums as soon as
 I start using them.

 > '''src/lib/dhcp/pkt4.h'''[[BR]]
 > Public constants in Pkt4 want a Doxygen-style comment before them.
 Added.

 > Typographical error in the DHCPV4_PKT_HDR_LEN comment - "specifes".
 Fixed.

 > In the Pkt4 constructor used for message transmission, does the first
 line require an "@brief" tag?
 Added.
 >
 > Same constructor, the "data" element is really a pointer to the data to
 be written to the message, not a pointer to received data.
 Comment was confusing. It is hopefully more readable now. That constructor
 is used when receiving data. Clarified that input data will be copied to
 bufferIn_.

 > Header comments for pack()/unpack(): there are no members named data_ or
 data_len_.
 Copy-and-paste error. Clarified that bufferIn_ and bufferOut_ will be
 used.

 > Header for unpack(): doesn't this parse a DHCPv4 packet, not a v6 one?
 Also, it should return true if the unpacking was successful, not if the
 "build" was successful.
 Fixed.

 > len(): a better description would be that len() returns the size of the
 required buffer to build the packet with the current set of packet
 options.
 Done.
 >
 > getSname()/getFile(): I think it would be safer to return a "const
 vector<uint8_t>" unless there is a very strong guarantee that the Pkt4
 structure will remain in existence while the the data is accessed.
 Done are requested. Note that is made use of this method both slower and
 more complicated. See changes in pkt4_unittest.cc.

 > setHWAddr(): there is the assumption that the macAddr argument points to
 an array that is long enough.  Passing in a "const vector<uint8_t>&" would
 be better in that the length can be checked.
 This function was implemented under the assumption that its user is a sane
 developer that understands that passing a pointer to a buffer and lying
 about its length will cause problems. As we do not know where MAC address
 date will come from (note that there could possibly be different sources
 of that information) at this stage, using const uint8_t* seems like a
 reasonable choice. Expanded comment to explain that and warn about passing
 hlen that is larger than buffer pointed by macAddr. Also added check if
 macAddr is NULL.

 >
 > Description of ifindex: "Windows" is spelt with a capital "W".  (You
 might not like it, but let's give it its proper name :-) ).
 How about wINDOWS? :-). Ok, fixed. It is now "MS Windows".
 >
 > op_ description (first line): This is the only line in the file that is
 more than 80 characters long (and 80 characters is the default width at
 which my editor opens).  Can we move the last word to the next line?
 It is now less than 80 characters long. Also expanded this description a
 bit.
 BTW What happened to the discussion about extending allowed line length to
 100?

 > chaddr_/sname_/file_ fields.  The declarations of the size of these
 arrays should use the constants defined earlier in the class.
 Done.

 > bufferIn_: We need to look again at the hooks interface.  I'm thinking
 that perhaps we don't need the buffer_rcvd() or buffer_end() callbacks -
 only let the users modify data in the form of a PktN& obejcts.  (besides,
 the DhcpHooks document advises against modifying the input or output wire
 data.) In this case, we are not passing a raw data buffer to the hooks and
 so bufferIn_ can be an !InputBuffer structure. (Not: if adopted, this
 requires a modification to DhcpHooks).
 I thought that we decided that on a high-level, hook user will have the
 ability to inject his changes on 2 levels: binary format and later at
 parsed options. There are valid cases when user may want to modify wire
 format - e.g. to fix fields for buggy clients, to recalculate checksums
 etc.

 It is true that user will have the ability to modify PktN& object, but we
 need to pass it twice. First, after we receive raw packet, we will pass it
 to buffer_rcvd(). Essential part is that hook can modify incoming packet.
 Therefore we must do parsing AFTER this hook returns. Then we parse this
 buffer, create options, set fields and so on. After parsing is complete,
 we call packet_rcvd() and user can tweak this packet further on a fields
 and options level.

 We could simplify this under the condition that there will be NO checks or
 any sort of processing between receiving buffer and parsing it. I can't
 specify any concrete examples at this moment, but I believe that one of
 useful functions of hooks at this stage would be conformance fix. Let me
 explain. Imagine a network with old devices that cannot be upgraded or
 migrated. Some of those older clients may send slightly malformed packets.
 We have first hand experience with cases when clients abused single domain
 option to send list of domains. One way of solving this problem is to
 implement hook that will fix such packets on the fly.

 > '''src/lib/dhcp/pkt6.cc'''[[BR]]
 > Constructors: for members that are of type IOAddress, there is no need
 to create an intermediate IOAddress object (i.e. ciaddr_("0.0.0.0") will
 work as well as ciaddr_(IOAddress("0.0.0.0")).  The former is initializing
 via a direct constructor, the latter is creating an intermediate object
 and initializing ciaddr_ via a copy constructor.
 >
 > Having said that, and at the risk of premature optimisation, there is a
 lot of parsing of "0.0.0.0" every time a Pkt4 object is created.  Would it
 be better to declare an external variable like:
 > {{{
 > namespace {
 > const IOAddress DEFAULT_ADDRESS("0.0.0.0");
 > }
 > }}}
 > ... and to initialize the address objects with a copy of
 DEFAULT_ADDRESS?  That way the parsing is only done once.
 Done.

 > setHWAddr: should be spaces around binary operators (i.e. "hlen >
 MAC_CHADDR_LEN").
 >
 > setHWAddr: can the macAddr be encapsulated in a vector (in which case
 there is no need to pass the hlen argument)?
 It could be. But hlen is a field in DHCPv4 packet. I prefer clean method
 that sets those fields as they are. Adding some logic that hlen will be
 set based on length of a vector is not the way to go here, especially
 since there are corner cases ahead. For example for Infiniband hlen is 20,
 but hlen field must be set to 0 and actual hardware address is stored in
 client-identifier option. htype, hlen and hardware address really should
 be set together in the simplest possible way.

 > setFile(): comment at the end of the method shows a cut and paste :-)
 Fixed.


 > '''src/lib/dhcp/tests/pkt4_unittest.cc'''[[BR]]
 > constructor: use the form "type* variable" instead of "type * variable".
 >
 > constructor: surround binary operators with spaces ("i = 0" instead of
 "i=0").
 Sorry for this recurring mistake. That's a notation I've been using for
 years and it's tricky to discard old habits.

 > constructor: even single-line "for" loops should have the statement
 enclosed in "{" and "}".
 Done.

 > Suggest starting comments with capital letters.
 Should comments form a complete sentence? I was trying to follow a logic
 that if a comment contains sentence, it should be formed as such (starting
 with capital letter and ending with a dot.). If it is just a short
 explanation, it is written in lower-case, without a dot.

 >
 > generateTestPacket1(): Space between parentheses in setFlags() call.
 >
 > generateTestPacket2(): I must admit I would have used a vector<> and a
 std::copy using a back_inserter object to copy data into it.  That way
 there is no chance of overflowing the buffer.
 I've never used back_inserter object. Could you commit code that does
 that?

 > fixedFields test - would prefer "EXPECT_EQ(0, memcmp(...)) to
 EXPECT_FALSE().
 Done.

 Fixes pushed to trac1224. Please re-review.

-- 
Ticket URL: <http://bind10.isc.org/ticket/1224#comment:7>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list