Commit d4a2bd9f authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3549] Changes after review:

 - It's called getMACFromIPv6() now
 - Tests for u,g bits added.
 - u bit is now flipped properly.
 - Unit tests updated to reflect above changes.
parent 0b5b2461
......@@ -169,7 +169,7 @@ Pkt::getMAC(uint32_t hw_addr_src) {
}
HWAddrPtr
Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) {
Pkt::getMACFromIPv6(const isc::asiolink::IOAddress& addr) {
if (!addr.isV6LinkLocal()) {
return (HWAddrPtr());
......@@ -183,6 +183,10 @@ Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) {
// Check that it's link-local (starts with fe80).
(bin[0] != 0xfe) || (bin[1] != 0x80) ||
// Check that u bit is set and g is clear. See Section 2.5.1 of RFC2373
// for details.
( (bin[0] & 3) != 2) ||
// And that the IID is of EUI-64 type.
(bin[11] != 0xff) || (bin[12] != 0xfe)) {
return (HWAddrPtr());
......@@ -194,6 +198,10 @@ Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) {
// Ok, we're down to EUI-64 only now: XX:XX:XX:ff:fe:XX:XX:XX
bin.erase(bin.begin() + 3, bin.begin() + 5);
// MAC-48 to EUI-64 involves inverting u bit (see explanation in Section
// 2.5.1 of RFC2373). We need to revert that.
bin[0] = bin[0] ^ 2;
// Let's get the interface this packet was received on. We need it to get
// hardware type
Iface* iface = IfaceMgr::instance().getIface(iface_);
......
......@@ -536,7 +536,7 @@ protected:
/// @param addr IPv6 address to be converted
/// @return hardware address (or NULL)
HWAddrPtr
getMACfromIPv6(const isc::asiolink::IOAddress& addr);
getMACFromIPv6(const isc::asiolink::IOAddress& addr);
/// Transaction-id (32 bits for v4, 24 bits for v6)
uint32_t transid_;
......
......@@ -546,11 +546,11 @@ HWAddrPtr
Pkt6::getMACFromSrcLinkLocalAddr() {
if (relay_info_.empty()) {
// This is a direct message, use source address
return (getMACfromIPv6(remote_addr_));
return (getMACFromIPv6(remote_addr_));
}
// This is a relayed message, get the peer-addr from the first relay-forw
return (getMACfromIPv6(relay_info_[relay_info_.size() - 1].peeraddr_));
return (getMACFromIPv6(relay_info_[relay_info_.size() - 1].peeraddr_));
}
......
......@@ -923,9 +923,12 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_direct) {
pkt.setIface(iface->getName());
pkt.setIndex(iface->getIndex());
// Note that u and g bits (the least significant ones of the most significant
// byte) have special meaning and must not be set in MAC. u bit is always set
// in EUI-64. g is always cleared.
IOAddress global("2001:db8::204:06ff:fe08:0a:0c");
IOAddress linklocal_eui64("fe80::204:06ff:fe08:0a0c");
IOAddress linklocal_noneui64("fe80::0204:0608:0a0c:0e10");
IOAddress linklocal_eui64("fe80::f204:06ff:fe08:0a0c");
IOAddress linklocal_noneui64("fe80::f204:0608:0a0c:0e10");
// If received from a global address, this method should fail
pkt.setRemoteAddr(global);
......@@ -937,7 +940,7 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_direct) {
ASSERT_TRUE(found);
stringstream tmp;
tmp << "hwtype=" << (int)iface->getHWType() << " 02:04:06:08:0a:0c";
tmp << "hwtype=" << (int)iface->getHWType() << " f0:04:06:08:0a:0c";
EXPECT_EQ(tmp.str(), found->toText(true));
}
......@@ -963,8 +966,8 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_singleRelay) {
pkt.setIndex(iface->getIndex());
IOAddress global("2001:db8::204:06ff:fe08:0a:0c"); // global address
IOAddress linklocal_noneui64("fe80::0204:0608:0a0c:0e10"); // no fffe
IOAddress linklocal_eui64("fe80::204:06ff:fe08:0a0c"); // valid EUI-64
IOAddress linklocal_noneui64("fe80::f204:0608:0a0c:0e10"); // no fffe
IOAddress linklocal_eui64("fe80::f204:06ff:fe08:0a0c"); // valid EUI-64
// If received from a global address, this method should fail
pkt.relay_info_[0].peeraddr_ = global;
......@@ -980,7 +983,7 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_singleRelay) {
ASSERT_TRUE(found);
stringstream tmp;
tmp << "hwtype=" << (int)iface->getHWType() << " 02:04:06:08:0a:0c";
tmp << "hwtype=" << (int)iface->getHWType() << " f0:04:06:08:0a:0c";
EXPECT_EQ(tmp.str(), found->toText(true));
}
......@@ -995,9 +998,9 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_multiRelay) {
// are stored in relay_info_ in the encapsulation order rather than in
// traverse order. The following simulates:
// client --- relay1 --- relay2 --- relay3 --- server
IOAddress linklocal1("fe80::ff:fe00:1"); // valid EUI-64
IOAddress linklocal2("fe80::ff:fe00:2"); // valid EUI-64
IOAddress linklocal3("fe80::ff:fe00:3"); // valid EUI-64
IOAddress linklocal1("fe80::200:ff:fe00:1"); // valid EUI-64
IOAddress linklocal2("fe80::200:ff:fe00:2"); // valid EUI-64
IOAddress linklocal3("fe80::200:ff:fe00:3"); // valid EUI-64
// Let's add info about relay3. This was the last relay, so it added the
// outermost encapsulation layer, so it was parsed first during reception.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment