Skip to content

Commit aa8eecb

Browse files
kellyyehyxieca
authored andcommitted
Add DHCPv6 Relay Agent (#8251)
* Added DHCPv6 Relay * Added DHCPv6 Counter
1 parent 27a2222 commit aa8eecb

File tree

13 files changed

+1430
-0
lines changed

13 files changed

+1430
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
group:isc-dhcp-relay

src/dhcp6relay/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
debian/*
2+
!debian/changelog
3+
!debian/compat
4+
!debian/control
5+
!debian/rules

src/dhcp6relay/Makefile

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
RM := rm -rf
2+
DHCP6RELAY_TARGET := dhcp6relay
3+
CP := cp
4+
MKDIR := mkdir
5+
CC := g++
6+
MV := mv
7+
LIBS := -levent -lhiredis -lswsscommon -pthread -lboost_thread -lboost_system -I $(PWD)/../sonic-swss-common/common
8+
CFLAGS = -g -Wall -std=gnu11
9+
PWD := $(shell pwd)
10+
11+
ifneq ($(MAKECMDGOALS),clean)
12+
ifneq ($(strip $(C_DEPS)),)
13+
-include $(C_DEPS) $(OBJS)
14+
endif
15+
endif
16+
17+
-include src/subdir.mk
18+
19+
all: sonic-dhcp6relay
20+
21+
sonic-dhcp6relay: $(OBJS)
22+
@echo 'Building target: $@'
23+
@echo 'Invoking: G++ Linker'
24+
$(CC) -o $(DHCP6RELAY_TARGET) $(OBJS) $(LIBS)
25+
@echo 'Finished building target: $@'
26+
@echo ' '
27+
28+
install:
29+
$(MKDIR) -p $(DESTDIR)/usr/sbin
30+
$(MV) $(DHCP6RELAY_TARGET) $(DESTDIR)/usr/sbin
31+
32+
deinstall:
33+
$(RM) $(DESTDIR)/usr/sbin/$(DHCP6RELAY_TARGET)
34+
$(RM) -rf $(DESTDIR)/usr/sbin
35+
36+
clean:
37+
-$(RM) $(EXECUTABLES) $(C_DEPS) $(OBJS) $(DHCP6RELAY_TARGET)
38+
-@echo ' '
39+
40+
.PHONY: all clean dependents
41+
42+

src/dhcp6relay/debian/changelog

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
sonic-dhcp6relay (1.0.0-0) UNRELEASED; urgency=medium
2+
3+
* Initial release.
4+
5+
-- Kelly Yeh <[email protected]>

src/dhcp6relay/debian/compat

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
9

src/dhcp6relay/debian/control

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Source: sonic-dhcp6relay
2+
Section: devel
3+
Priority: optional
4+
Maintainer: Kelly Yeh <[email protected]>
5+
Build-Depends: debhelper (>= 8.0.0),
6+
dh-systemd
7+
Standards-Version: 3.9.3
8+
Homepage: https://github.com/Azure/sonic-buildimage
9+
XS-Go-Import-Path: github.com/Azure/sonic-buildimage
10+
11+
Package: sonic-dhcp6relay
12+
Architecture: any
13+
Built-Using: ${misc:Built-Using}
14+
Depends: libevent-2.1-6,
15+
libboost-thread1.71.0,
16+
libboost-system1.71.0
17+
Description: SONiC DHCPv6 Relay

src/dhcp6relay/debian/rules

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/make -f
2+
3+
%:
4+
dh $@ --parallel
+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include <sstream>
2+
#include <syslog.h>
3+
#include <algorithm>
4+
#include "configInterface.h"
5+
6+
constexpr auto DEFAULT_TIMEOUT_MSEC = 1000;
7+
8+
bool pollSwssNotifcation = true;
9+
std::shared_ptr<boost::thread> mSwssThreadPtr;
10+
11+
std::shared_ptr<swss::DBConnector> configDbPtr = std::make_shared<swss::DBConnector> ("CONFIG_DB", 0);
12+
swss::SubscriberStateTable ipHelpersTable(configDbPtr.get(), "DHCP_RELAY");
13+
swss::Select swssSelect;
14+
15+
/**
16+
* @code void deinitialize_swss()
17+
*
18+
* @brief initialize DB tables and start SWSS listening thread
19+
*
20+
* @return none
21+
*/
22+
void initialize_swss(std::vector<relay_config> *vlans, swss::DBConnector *db)
23+
{
24+
try {
25+
swssSelect.addSelectable(&ipHelpersTable);
26+
get_dhcp(vlans);
27+
mSwssThreadPtr = std::make_shared<boost::thread> (&handleSwssNotification, vlans);
28+
}
29+
catch (const std::bad_alloc &e) {
30+
syslog(LOG_ERR, "Failed allocate memory. Exception details: %s", e.what());
31+
}
32+
}
33+
34+
/**
35+
* @code void deinitialize_swss()
36+
*
37+
* @brief deinitialize DB interface and join SWSS listening thread
38+
*
39+
* @return none
40+
*/
41+
void deinitialize_swss()
42+
{
43+
stopSwssNotificationPoll();
44+
mSwssThreadPtr->interrupt();
45+
}
46+
47+
48+
/**
49+
* @code void get_dhcp(std::vector<relay_config> *vlans)
50+
*
51+
* @brief initialize and get vlan table information from DHCP_RELAY
52+
*
53+
* @return none
54+
*/
55+
void get_dhcp(std::vector<relay_config> *vlans) {
56+
swss::Selectable *selectable;
57+
int ret = swssSelect.select(&selectable, DEFAULT_TIMEOUT_MSEC);
58+
if (ret == swss::Select::ERROR) {
59+
syslog(LOG_WARNING, "Select: returned ERROR");
60+
} else if (ret == swss::Select::TIMEOUT) {
61+
}
62+
if (selectable == static_cast<swss::Selectable *> (&ipHelpersTable)) {
63+
handleRelayNotification(ipHelpersTable, vlans);
64+
}
65+
}
66+
/**
67+
* @code void handleSwssNotification(std::vector<relay_config> *vlans)
68+
*
69+
* @brief main thread for handling SWSS notification
70+
*
71+
* @param context list of vlans/argument config that contains strings of server and option
72+
*
73+
* @return none
74+
*/
75+
void handleSwssNotification(std::vector<relay_config> *vlans)
76+
{
77+
while (pollSwssNotifcation) {
78+
get_dhcp(vlans);
79+
}
80+
}
81+
82+
/**
83+
* @code void handleRelayNotification(swss::SubscriberStateTable &ipHelpersTable, std::vector<relay_config> *vlans)
84+
*
85+
* @brief handles DHCPv6 relay configuration change notification
86+
*
87+
* @param ipHelpersTable DHCP table
88+
* @param context list of vlans/argument config that contains strings of server and option
89+
*
90+
* @return none
91+
*/
92+
void handleRelayNotification(swss::SubscriberStateTable &ipHelpersTable, std::vector<relay_config> *vlans)
93+
{
94+
std::deque<swss::KeyOpFieldsValuesTuple> entries;
95+
96+
ipHelpersTable.pops(entries);
97+
processRelayNotification(entries, vlans);
98+
}
99+
100+
/**
101+
* @code void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries, std::vector<relay_config> *vlans)
102+
*
103+
* @brief process DHCPv6 relay servers and options configuration change notification
104+
*
105+
* @param entries queue of std::tuple<std::string, std::string, std::vector<FieldValueTuple>> entries in DHCP table
106+
* @param context list of vlans/argument config that contains strings of server and option
107+
*
108+
* @return none
109+
*/
110+
void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries, std::vector<relay_config> *vlans)
111+
{
112+
std::vector<std::string> servers;
113+
114+
for (auto &entry: entries) {
115+
std::string vlan = kfvKey(entry);
116+
std::string operation = kfvOp(entry);
117+
std::vector<swss::FieldValueTuple> fieldValues = kfvFieldsValues(entry);
118+
119+
relay_config intf;
120+
intf.interface = vlan;
121+
for (auto &fieldValue: fieldValues) {
122+
std::string f = fvField(fieldValue);
123+
std::string v = fvValue(fieldValue);
124+
if(f == "dhcpv6_servers") {
125+
std::stringstream ss(v);
126+
while (ss.good()) {
127+
std::string substr;
128+
getline(ss, substr, ',');
129+
intf.servers.push_back(substr);
130+
}
131+
syslog(LOG_DEBUG, "key: %s, Operation: %s, f: %s, v: %s", vlan.c_str(), operation.c_str(), f.c_str(), v.c_str());
132+
}
133+
if(f == "dhcpv6_option|rfc6939_support") {
134+
if(v == "true")
135+
intf.is_option_79 = true;
136+
else if(v == "false")
137+
intf.is_option_79 = false;
138+
}
139+
}
140+
vlans->push_back(intf);
141+
}
142+
}
143+
144+
/**
145+
*@code stopSwssNotificationPoll
146+
*
147+
*@brief stop SWSS listening thread
148+
*
149+
*@return none
150+
*/
151+
void stopSwssNotificationPoll() {
152+
pollSwssNotifcation = false;
153+
};

src/dhcp6relay/src/configInterface.h

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <boost/thread.hpp>
2+
#include "subscriberstatetable.h"
3+
#include "select.h"
4+
#include "relay.h"
5+
6+
/**
7+
* @code void deinitialize_swss()
8+
*
9+
* @brief initialize DB tables and start SWSS listening thread
10+
*
11+
* @return none
12+
*/
13+
void initialize_swss(std::vector<relay_config> *vlans, swss::DBConnector *db);
14+
15+
/**
16+
* @code void deinitialize_swss()
17+
*
18+
* @brief deinitialize DB interface and join SWSS listening thread
19+
*
20+
* @return none
21+
*/
22+
void deinitialize_swss();
23+
24+
/**
25+
* @code void get_dhcp(std::vector<relay_config> *vlans)
26+
*
27+
* @brief initialize and get vlan information from DHCP_RELAY
28+
*
29+
* @return none
30+
*/
31+
void get_dhcp(std::vector<relay_config> *vlans);
32+
33+
/**
34+
* @code void handleSwssNotification(std::vector<relay_config> *vlans)
35+
*
36+
* @brief main thread for handling SWSS notification
37+
*
38+
* @param context list of vlans/argument config that contains strings of server and option
39+
*
40+
* @return none
41+
*/
42+
void handleSwssNotification(std::vector<relay_config> *vlans);
43+
44+
/**
45+
* @code void handleRelayNotification(swss::SubscriberStateTable &ipHelpersTable, std::vector<relay_config> *vlans)
46+
*
47+
* @brief handles DHCPv6 relay configuration change notification
48+
*
49+
* @param ipHelpersTable DHCP table
50+
* @param context list of vlans/argument config that contains strings of server and option
51+
*
52+
* @return none
53+
*/
54+
void handleRelayNotification(swss::SubscriberStateTable &configMuxTable, std::vector<relay_config> *vlans);
55+
56+
/**
57+
* @code void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries, std::vector<relay_config> *vlans)
58+
*
59+
* @brief process DHCPv6 relay servers and options configuration change notification
60+
*
61+
* @param entries queue of std::tuple<std::string, std::string, std::vector<FieldValueTuple>> entries in DHCP table
62+
* @param context list of vlans/argument config that contains strings of server and option
63+
*
64+
* @return none
65+
*/
66+
void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries, std::vector<relay_config> *vlans);
67+
68+
/**
69+
*@code stopSwssNotificationPoll
70+
*
71+
*@brief stop SWSS listening thread
72+
*
73+
*@return none
74+
*/
75+
void stopSwssNotificationPoll();

src/dhcp6relay/src/main.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdlib.h>
2+
#include <syslog.h>
3+
#include "configInterface.h"
4+
5+
int main(int argc, char *argv[]) {
6+
try {
7+
std::vector<relay_config> vlans;
8+
swss::DBConnector state_db("STATE_DB", 0);
9+
initialize_swss(&vlans, &state_db);
10+
loop_relay(&vlans, &state_db);
11+
}
12+
catch (std::exception &e)
13+
{
14+
syslog(LOG_ERR, "An exception occurred.\n");
15+
return 1;
16+
}
17+
return 0;
18+
}

0 commit comments

Comments
 (0)