Skip to content

Add ARP Responder module - #494

Merged
sangjinhan merged 5 commits into
NetSys:masterfrom
GalSagie:add_arp_responder_module
Jun 6, 2017
Merged

Add ARP Responder module#494
sangjinhan merged 5 commits into
NetSys:masterfrom
GalSagie:add_arp_responder_module

Conversation

@GalSagie

@GalSagie GalSagie commented Jun 1, 2017

Copy link
Copy Markdown
Contributor

ARP responder is configured with known MAC's-IP's pairs
and know to answer ARP requests depending on its configured cache.

This module can be used to implement virtual routing in
virtual enviorments and also as a foundation for ARP
handling in general.

Still todo is the ability to learn new MAC-IP pairs from
the requests and replys and also removing of pairs
from cache (with maybe potential timeouts)

GalSagie added 2 commits June 1, 2017 11:12
ARP responder is configured with known MAC's-IP's pairs
and know to answer ARP requests depending on its configured cache.

This module can be used to implement virtual routing in
virtual enviorments and also as a foundation for ARP
handling in general.

Still todo is the ability to learn new MAC-IP pairs from
the requests and replys and also removing of pairs
from cache (with maybe potential timeouts)
add new lines at end of files
@codecov

codecov Bot commented Jun 1, 2017

Copy link
Copy Markdown

Codecov Report

Merging #494 into master will increase coverage by 28%.
The diff coverage is 80%.

Impacted file tree graph

@@           Coverage Diff            @@
##           master    #494     +/-   ##
========================================
+ Coverage      30%     58%    +28%     
========================================
  Files         168     178     +10     
  Lines        8181   10203   +2022     
  Branches     1556       0   -1556     
========================================
+ Hits         2489    5947   +3458     
+ Misses       5310    4256   -1054     
+ Partials      382       0    -382
Impacted Files Coverage Δ
core/modules/arp_responder.h 100% <100%> (ø)
core/modules/arp_responder.cc 79% <79%> (ø)
core/modules/merge.cc 25% <0%> (-8%) ⬇️
core/metadata.h 64% <0%> (-3%) ⬇️
core/message.h 18% <0%> (-2%) ⬇️
core/modules/ip_checksum.cc 11% <0%> (-1%) ⬇️
core/modules/buffer.cc 4% <0%> (-1%) ⬇️
core/modules/timestamp.cc 4% <0%> (-1%) ⬇️
core/modules/generic_decap.cc 7% <0%> (ø) ⬇️
core/modules/port_out.cc 3% <0%> (ø) ⬇️
... and 140 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 024c1b9...103164b. Read the comment docs.

using bess::utils::Ethernet;
using bess::utils::be32_t;

struct arp_entry {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment for struct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread core/modules/arp_responder.h Outdated
struct arp_entry {
Ethernet::Address mac_addr;
be32_t ip_addr;
uint64_t time;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you describe time, especially its units?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, added that its timestamp, its currently not used but will be in future patches

Comment thread core/modules/arp_responder.h Outdated
CommandResponse CommandAdd(const bess::pb::ArpResponderArg &arg);

private:
std::map<be32_t, arp_entry> entries;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Member variable comment.

Also entries should be named entries_ and by general convention perhaps use struct arp_entry rather than arp_entry.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


CommandResponse ArpResponder::CommandAdd(const bess::pb::ArpResponderArg &arg) {
be32_t ip_addr;
arp_entry entry;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to declare entry.

@GalSagie GalSagie Jun 1, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below

Comment thread core/modules/arp_responder.cc Outdated

entry.mac_addr.FromString(arg.mac_addr());
entry.ip_addr = ip_addr;
entries[ip_addr] = entry;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can brace initialize entry here with all of its fields.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the mac is now filled as part of a check (see fix above) and its a bit hard to do it now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you aren't brace initializing, could you explicitly initialize time? Otherwise I believe it is uninitialized.

Comment thread core/modules/arp_responder.cc Outdated
return CommandFailure(EINVAL, "Invalid IP Address: %s", arg.ip().c_str());
}

entry.mac_addr.FromString(arg.mac_addr());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you not want to check the MAC address just like you do the IP address?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

uint64_t time;
};

class ArpResponder final : public Module {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a class comment. Specifically, you may want to mention here (or somewhere) that this module drops non-ARP packets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread core/modules/arp_responder.cc Outdated

Arp *arp = reinterpret_cast<Arp *>(eth + 1);
if (arp->opcode == be16_t(Arp::Opcode::kRequest)) {
// TODO When learn is added, learn SRC MAC here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change TODO to have your name, e.g. TODO(galsagie), here and below?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


struct arp_entry {
Ethernet::Address mac_addr;
be32_t ip_addr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ip_addr redundant given that it is the key of the map below?

@GalSagie GalSagie Jun 1, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is redundant, i prefer to leave it currently for clarity and optimize in later patch
If you think strongly about it, i will use the key

Comment thread core/modules/arp_responder.cc Outdated
// Try to find target IP in cache, if exists convert request to reply
auto it = entries.find(arp->target_ip_addr);
if (it != entries.end()) {
struct arp_entry *entry = &it->second;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer a const reference, e.g.:

const struct arp_entry &entry = it->second

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Address code review comments
Comment thread core/modules/arp_responder.cc Outdated
// Try to find target IP in cache, if exists convert request to reply
auto it = entries_.find(arp->target_ip_addr);
if (it != entries_.end()) {
const struct arp_entry &entry = it->second;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you run clang-format to fix this and anything else it finds?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread core/modules/arp_responder.h Outdated
struct arp_entry {
Ethernet::Address mac_addr;
be32_t ip_addr;
// timestamp used to expire cache entries

@barath barath Jun 1, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: since the other fields don't have comments, perhaps move the comment to the same line as time. Also, could you include the units?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Address code review comments
Comment thread core/modules/arp_responder.cc Outdated
for (int i = 0; i < cnt; i++) {
bess::Packet *pkt = batch->pkts()[i];

out_gates[i] = incoming_gate;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the module has only one input/output gate, you can just assign 0. Unfortunately get_igate() is not free... :(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread bessctl/conf/samples/arp.bess Outdated
import scapy.all as scapy

eth_header = scapy.Ether(src='02:1e:67:9f:4d:ae', dst='ff:ff:ff:ff:ff:ff')
arp_header = scapy.ARP(op=1, pdst='1.1.1.1')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use another IP address that is not symmetric? Just as a safety measure for subtle endianness regression bugs later any time...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread bessctl/conf/samples/arp.bess Outdated
pkt = eth_header/arp_header
packets = [str(pkt)]

arp = ArpResponder(name="arp")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name="arp" is set but not used below. For conciseness, this line can be replaced with either:

arp::ArpResponder()  # this is identical to the original statement

or

arp = ArpResponder()  # the resulting (default) name will be arp_responder0

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread bessctl/conf/samples/arp.bess Outdated
packets = [str(pkt)]

arp = ArpResponder(name="arp")
arp.add(ip='1.1.1.1', mac_addr='11:22:33:44:55:66')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really a minor thing, but the MAC address is multicast :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

arp->sender_ip_addr = entry.ip_addr;
}
} else if (arp->opcode == be16_t(Arp::Opcode::kReply)) {
// TODO(galsagie) When learn is added, learn SRC MAC here

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these two else blocks should discard (after learning if necessary) the packet as well...? Otherwise, its downstream modules has to figure out what to do with the packets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread protobuf/module_msg.proto Outdated
}

/**
* The ARP Responder module is responding to ARP requests and can optionally learn new MAC's-IP's mapping

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment "can optionally learn ..." can be updated so as to be clear that it is not supported yet...? For example, "TODO:"

Q: is the ARP learning feature for proxy ARP?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, yes it can be used for a proxy ARP and it can also be used later for "full" ARP layer implementation to the local host.

Address code review comments,
1) Drop ARP packets in case no cache entry is found and
not an ARP request
2) Update TODO's
3) Use 0 as the default incoming gate
@sangjinhan
sangjinhan merged commit 0129500 into NetSys:master Jun 6, 2017
@sangjinhan

Copy link
Copy Markdown
Member

Merged, thanks!
tumblr_m9q1andspd1qd477zo1_500

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants