Skip to content

Commit 939fbd2

Browse files
committed
[#4358] Fixed L2 relay support
1 parent 90a5088 commit 939fbd2

3 files changed

Lines changed: 74 additions & 7 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[bug] fdupont
2+
Extended DHCPv6 relayed query processing to consider
3+
the 'interface-id' option (18) in subnet selection
4+
even when no relay sets its link-address to a global
5+
unicast address, e.g. is a layer-2 relay.
6+
(Gitlab #4358)

src/lib/dhcpsrv/cfg_subnets6.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ CfgSubnets6::initSelector(const Pkt6Ptr& query) {
211211
// Initialize fields specific to relayed messages.
212212
if (!query->relay_info_.empty()) {
213213
for (auto const& relay : boost::adaptors::reverse(query->relay_info_)) {
214+
// Note that a link local address is useless so skip it.
214215
if (!relay.linkaddr_.isV6Zero() &&
215216
!relay.linkaddr_.isV6LinkLocal()) {
216217
selector.first_relay_linkaddr_ = relay.linkaddr_;
@@ -229,9 +230,10 @@ ConstSubnet6Ptr
229230
CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
230231
ConstSubnet6Ptr subnet;
231232

232-
// If relay agent link address is set to zero it means that we're dealing
233-
// with a directly connected client.
234-
if (selector.first_relay_linkaddr_ == IOAddress("::")) {
233+
// If relay agent link address is set to zero and there is no interface id
234+
// it means that we're dealing with a directly connected client.
235+
if ((selector.first_relay_linkaddr_ == IOAddress("::")) &&
236+
!selector.interface_id_) {
235237
// If interface name is known try to match it with interface names
236238
// specified for configured subnets.
237239
if (!selector.iface_name_.empty()) {
@@ -252,7 +254,7 @@ CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
252254

253255
// If Interface ID option could not be matched for any subnet, try
254256
// the relay agent link address.
255-
if (!subnet) {
257+
if (!subnet && (selector.first_relay_linkaddr_ != IOAddress("::"))) {
256258
subnet = selectSubnet(selector.first_relay_linkaddr_,
257259
selector.client_classes_,
258260
true);

src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ TEST(CfgSubnets6Test, selectSubnetByNetworkRelayAddress) {
372372
}
373373

374374
// This test checks that the subnet can be selected using an interface
375-
// name associated with a asubnet.
375+
// name associated with a subnet.
376376
TEST(CfgSubnets6Test, selectSubnetByInterfaceName) {
377377
CfgSubnets6 cfg;
378378

@@ -422,7 +422,7 @@ TEST(CfgSubnets6Test, selectSubnetByInterfaceName) {
422422
}
423423

424424
// This test checks that the subnet can be selected using an Interface ID
425-
// option inserted by a relay.
425+
// option inserted by a relay (TODO: merge with the L2 variant).
426426
TEST(CfgSubnets6Test, selectSubnetByInterfaceId) {
427427
CfgSubnets6 cfg;
428428

@@ -482,6 +482,65 @@ TEST(CfgSubnets6Test, selectSubnetByInterfaceId) {
482482
EXPECT_FALSE(cfg.selectSubnet(selector));
483483
}
484484

485+
// This test checks that the subnet can be selected using an Interface ID
486+
// option inserted by a L2 relay.
487+
TEST(CfgSubnets6Test, selectSubnetByInterfaceIdL2) {
488+
CfgSubnets6 cfg;
489+
490+
// Create 3 subnets.
491+
Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"),
492+
48, 1, 2, 3, 4, SubnetID(1)));
493+
Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"),
494+
48, 1, 2, 3, 4, SubnetID(2)));
495+
Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"),
496+
48, 1, 2, 3, 4, SubnetID(3)));
497+
498+
// Create Interface-id options used in subnets 1,2, and 3
499+
OptionPtr ifaceid1 = generateInterfaceId("relay1.eth0");
500+
OptionPtr ifaceid2 = generateInterfaceId("VL32");
501+
// That's a strange interface-id, but this is a real life example
502+
OptionPtr ifaceid3 = generateInterfaceId("ISAM144|299|ipv6|nt:vp:1:110");
503+
504+
// Bogus interface-id.
505+
OptionPtr ifaceid_bogus = generateInterfaceId("non-existent");
506+
507+
// Assign interface ids to the respective subnets.
508+
subnet1->setInterfaceId(ifaceid1);
509+
subnet2->setInterfaceId(ifaceid2);
510+
subnet3->setInterfaceId(ifaceid3);
511+
512+
// There shouldn't be any subnet configured at this stage.
513+
SubnetSelector selector;
514+
selector.interface_id_ = ifaceid1;
515+
// No longer need to set the relay link address.
516+
EXPECT_FALSE(cfg.selectSubnet(selector));
517+
518+
// Add one of the subnets.
519+
cfg.add(subnet1);
520+
521+
// If only one subnet has been specified, it should be returned when the
522+
// interface id matches. But, for a different interface id there should be
523+
// no match.
524+
EXPECT_EQ(subnet1, cfg.selectSubnet(selector));
525+
selector.interface_id_ = ifaceid2;
526+
EXPECT_FALSE(cfg.selectSubnet(selector));
527+
528+
// Add other subnets.
529+
cfg.add(subnet2);
530+
cfg.add(subnet3);
531+
532+
// Now that we have all subnets added. we should be able to retrieve them
533+
// using appropriate interface ids.
534+
selector.interface_id_ = ifaceid3;
535+
EXPECT_EQ(subnet3, cfg.selectSubnet(selector));
536+
selector.interface_id_ = ifaceid2;
537+
EXPECT_EQ(subnet2, cfg.selectSubnet(selector));
538+
539+
// For invalid interface id, there should be nothing returned.
540+
selector.interface_id_ = ifaceid_bogus;
541+
EXPECT_FALSE(cfg.selectSubnet(selector));
542+
}
543+
485544
// Test that the client classes are considered when the subnet is selected by
486545
// the relay link address.
487546
TEST(CfgSubnets6Test, selectSubnetByRelayAddressAndClassify) {
@@ -626,7 +685,7 @@ TEST(CfgSubnets6Test, selectSubnetByInterfaceIdAndClassify) {
626685
// If we have only a single subnet and the request came from a local
627686
// address, let's use that subnet
628687
SubnetSelector selector;
629-
selector.first_relay_linkaddr_ = IOAddress("5000::1");
688+
// No longer need to set the relay link address.
630689
selector.client_classes_.insert("bar");
631690
selector.interface_id_ = ifaceid1;
632691
EXPECT_EQ(subnet1, cfg.selectSubnet(selector));

0 commit comments

Comments
 (0)