Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions modules/network/dhcp-1/bin/isc-dhcp-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

CONFIG_FILE=/etc/dhcp/dhcpd.conf
DHCP_PID_FILE=/var/run/dhcpd.pid
DHCP_LOG_FILE=/runtime/network/dhcp1-dhcpd.log

stop_dhcp(){
# Directly kill by PID file reference
if [ -f "$DHCP_PID_FILE" ]; then
kill -9 $(cat $DHCP_PID_FILE) || true
rm -f $DHCP_PID_FILE
fi
}

start_dhcp(){
/usr/sbin/dhcpd -d &> $DHCP_LOG_FILE &
}

case "$1" in
start)
start_dhcp
;;
stop)
stop_dhcp
;;
restart)
stop_dhcp
sleep 1
start_dhcp
;;
status)
if [ -f "$DHCP_PID_FILE" ]; then
echo "isc-dhcp service is running."
else
echo "isc-dhcp service is not running."
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac
4 changes: 3 additions & 1 deletion modules/network/dhcp-1/bin/start_network_service
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ cp /testrun/conf/isc-dhcp-server /etc/default/
cp /testrun/conf/dhcpd.conf /etc/dhcp/dhcpd.conf
cp /testrun/conf/radvd.conf /etc/radvd.conf

# Move the radvd-sevice file to the correct location

# Move the service files to the correct location
cp /testrun/bin/isc-dhcp-service /usr/local/bin/
cp /testrun/bin/radvd-service /usr/local/bin/

# Start the DHCP Server
Expand Down
5 changes: 3 additions & 2 deletions modules/network/dhcp-1/conf/dhcpd.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
default-lease-time 300;
default-lease-time 30;
max-lease-time 30;

failover peer "failover-peer" {
primary;
Expand All @@ -8,7 +9,7 @@ failover peer "failover-peer" {
peer port 647;
max-response-delay 60;
max-unacked-updates 10;
mclt 3600;
mclt 30;
split 128;
load balance max seconds 3;
}
Expand Down
2 changes: 1 addition & 1 deletion modules/network/dhcp-1/conf/isc-dhcp-server
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="veth0"
#INTERFACESv6="veth0"
#INTERFACESv6="veth0"
23 changes: 11 additions & 12 deletions modules/network/dhcp-1/conf/radvd.conf
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
interface veth0
{
AdvSendAdvert on;
AdvManagedFlag off;
MinRtrAdvInterval 30;
MaxRtrAdvInterval 60;
prefix fd10:77be:4186::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
AdvSourceLLAddress off;
};
interface veth0
{
AdvSendAdvert on;
AdvManagedFlag off;
MinRtrAdvInterval 30;
MaxRtrAdvInterval 60;
prefix fd10:77be:4186::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
};
};
67 changes: 57 additions & 10 deletions modules/network/dhcp-1/python/src/grpc_server/dhcp_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
LOGGER = None
CONFIG_FILE = '/etc/dhcp/dhcpd.conf'
DEFAULT_LEASE_TIME_KEY = 'default-lease-time'
MAX_LEASE_TIME_KEY = 'max-lease-time'


class DHCPConfig:
"""Represents the DHCP Servers configuration and gives access to modify it"""

def __init__(self):
self._default_lease_time = 300
self._default_lease_time = 30
self._max_lease_time = 30
self._subnets = []
self._peer = None
self._reserved_hosts = []
Expand Down Expand Up @@ -120,17 +122,50 @@ def set_range(self, start, end, subnet=0, pool=0):
octets[-1] = '0'
dhcp_subnet = '.'.join(octets)

#Update the subnet and range
self._subnets[subnet].set_subnet(dhcp_subnet)
# Calcualte the netmask from the range
prefix = self.calculate_prefix_length(start, end)
netmask = self.calculate_netmask(prefix)

#Update the subnet, range and netmask
self._subnets[subnet].set_subnet(dhcp_subnet, netmask)
self._subnets[subnet].pools[pool].set_range(start, end)

def calculate_prefix_length(self, start_ip, end_ip):
start_octets = start_ip.split('.')
end_octets = end_ip.split('.')

start_int = int(
''.join(format(int(octet), '08b') for octet in start_octets), 2)
end_int = int(''.join(format(int(octet), '08b') for octet in end_octets), 2)

xor_result = start_int ^ end_int
prefix_length = 32 - xor_result.bit_length()

return prefix_length

def calculate_netmask(self, prefix_length):
num_network_bits = prefix_length
num_host_bits = 32 - num_network_bits

netmask_int = (2**num_network_bits - 1) << num_host_bits
netmask_octets = [(netmask_int >> (i * 8)) & 0xff for i in range(3, -1, -1)]

return '.'.join(str(octet) for octet in netmask_octets)

def __str__(self):

config = ('{DEFAULT_LEASE_TIME_KEY} {DEFAULT_LEASE_TIME};'
if self._default_lease_time is not None else '')
config += ('\n\r{MAX_LEASE_TIME_KEY} {MAX_LEASE_TIME};'
if self._max_lease_time is not None else '')

# Encode the top level config options
config = """{DEFAULT_LEASE_TIME_KEY} {DEFAULT_LEASE_TIME};"""
#config = """{DEFAULT_LEASE_TIME_KEY} {DEFAULT_LEASE_TIME};"""
config = config.format(length='multi-line',
DEFAULT_LEASE_TIME_KEY=DEFAULT_LEASE_TIME_KEY,
DEFAULT_LEASE_TIME=self._default_lease_time)
DEFAULT_LEASE_TIME=self._default_lease_time,
MAX_LEASE_TIME_KEY=MAX_LEASE_TIME_KEY,
MAX_LEASE_TIME=self._max_lease_time)

# Encode the failover peer
config += '\n\n' + str(self._peer)
Expand Down Expand Up @@ -358,12 +393,24 @@ def set_subnet(self, subnet, netmask=None):
self._subnet = subnet
self._subnet_mask = netmask

# Calculate the broadcast from the subnet
octets = subnet.split('.')
octets[-1] = '255'
dhcp_broadcast = '.'.join(octets)
# Calculate the broadcast from the subnet and netmask
broadcast = self.calculate_broadcast_address(subnet, netmask)
self._broadcast = broadcast

def calculate_broadcast_address(self, subnet_address, netmask):
subnet_octets = subnet_address.split('.')
netmask_octets = netmask.split('.')

subnet_int = int(
''.join(format(int(octet), '08b') for octet in subnet_octets), 2)
netmask_int = int(
''.join(format(int(octet), '08b') for octet in netmask_octets), 2)

broadcast_int = subnet_int | (~netmask_int & 0xffffffff)
broadcast_octets = [(broadcast_int >> (i * 8)) & 0xff
for i in range(3, -1, -1)]

self._broadcast = dhcp_broadcast
return '.'.join(str(octet) for octet in broadcast_octets)

def resolve_subnet(self, subnet):
subnet_parts = subnet.split('\n')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
CONFIG_FILE = 'conf/dhcpd.conf'
DHCP_CONFIG = None


def get_config_file_path():
current_dir = os.path.dirname(os.path.abspath(__file__))
module_dir = os.path.dirname(
Expand Down Expand Up @@ -91,6 +92,15 @@ def test_resolve_config_with_hosts(self):
self.assertIsNotNone(host)
print('ResolveConfigWithHosts:\n' + str(config_with_hosts))

def test_set_subnet_range(self):
range_start = '10.0.0.100'
range_end = '10.0.0.200'
DHCP_CONFIG.set_range(range_start, range_end)
subnets = DHCP_CONFIG.resolve_subnets(str(DHCP_CONFIG))
pool = subnets[0].pools[0]
self.assertTrue(pool.range_start == range_start
and pool.range_end == range_end)
print('SetSubnetRange:\n' + str(DHCP_CONFIG))

if __name__ == '__main__':
suite = unittest.TestSuite()
Expand All @@ -100,6 +110,6 @@ def test_resolve_config_with_hosts(self):
suite.addTest(DHCPConfigTest('test_add_reserved_host'))
suite.addTest(DHCPConfigTest('test_delete_reserved_host'))
suite.addTest(DHCPConfigTest('test_resolve_config_with_hosts'))

suite.addTest(DHCPConfigTest('test_set_subnet_range'))
runner = unittest.TextTestRunner()
runner.run(suite)
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _make_lease(self, lease):
self.hw_addr = sections[0]
self.ip = sections[1]
self.hostname = sections[2]
self.expires = sections[3] + '' '' + sections[4]
self.expires = sections[3] + ' ' + sections[4]
self.manufacturer = ' '.join(sections[5:])

def get_millis(self, timestamp):
Expand Down
6 changes: 3 additions & 3 deletions modules/network/dhcp-1/python/src/grpc_server/dhcp_leases.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ def get_leases(self):
leases = []
lease_list_raw = self._get_lease_list()
LOGGER.info('Raw Leases:\n' + str(lease_list_raw) + '\n')
lease_list_start = lease_list_raw.find('=========',0)
lease_list_start = lease_list_raw.find('\n',lease_list_start)
lease_list = lease_list_raw[lease_list_start+1:]
lease_list_start = lease_list_raw.find('=========', 0)
lease_list_start = lease_list_raw.find('\n', lease_list_start)
lease_list = lease_list_raw[lease_list_start + 1:]
lines = lease_list.split('\n')
for line in lines:
try:
Expand Down
13 changes: 7 additions & 6 deletions modules/network/dhcp-1/python/src/grpc_server/dhcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,32 @@ def __init__(self):

def restart(self):
LOGGER.info('Restarting DHCP Server')
isc_started = util.run_command('service isc-dhcp-server restart', False)
isc_started = util.run_command('isc-dhcp-service restart', False)
radvd_started = self.radvd.restart()
started = isc_started and radvd_started
LOGGER.info('DHCP Restarted: ' + str(started))
return started

def start(self):
LOGGER.info('Starting DHCP Server')
isc_started = util.run_command('service isc-dhcp-server start', False)
isc_started = util.run_command('isc-dhcp-service start', False)
radvd_started = self.radvd.start()
started = isc_started and radvd_started
LOGGER.info('DHCP Started: ' + str(started))
return started

def stop(self):
LOGGER.info('Stopping DHCP Server')
isc_stopped = util.run_command('service isc-dhcp-server stop', False)
isc_stopped = util.run_command('isc-dhcp-service stop', False)
radvd_stopped = self.radvd.stop()
stopped = isc_stopped and radvd_stopped
LOGGER.info('DHCP Stopped: ' + str(stopped))
return stopped

def is_running(self):
LOGGER.info('Checking DHCP Status')
response = util.run_command('service isc-dhcp-server status')
isc_running = response[
0] == 'Status of ISC DHCPv4 server: dhcpd is running.'
response = util.run_command('isc-dhcp-service status')
isc_running = response[0] == 'isc-dhcp service is running.'
radvd_running = self.radvd.is_running()
running = isc_running and radvd_running
LOGGER.info('DHCP Status: ' + str(running))
Expand Down Expand Up @@ -107,6 +106,7 @@ def boot(self):

return isc_booted and radvd_booted


def run():
dhcp_server = DHCPServer()
booted = dhcp_server.boot()
Expand All @@ -126,5 +126,6 @@ def run():
dhcp_server.radvd.restart()
time.sleep(1)


if __name__ == '__main__':
run()
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
LOG_NAME = 'network_service'
LOGGER = None


class NetworkService(pb2_grpc.NetworkModule):
"""gRPC endpoints for the DHCP Server"""

Expand Down
56 changes: 56 additions & 0 deletions modules/network/dhcp-2/bin/isc-dhcp-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

CONFIG_FILE=/etc/dhcp/dhcpd.conf
DHCP_PID_FILE=/var/run/dhcpd.pid
DHCP_LOG_FILE=/runtime/network/dhcp2-dhcpd.log

stop_dhcp(){
# Directly kill by PID file reference
if [ -f "$DHCP_PID_FILE" ]; then
kill -9 $(cat $DHCP_PID_FILE) || true
rm -f $DHCP_PID_FILE
fi
}

start_dhcp(){
/usr/sbin/dhcpd -d &> $DHCP_LOG_FILE &
}

case "$1" in
start)
start_dhcp
;;
stop)
stop_dhcp
;;
restart)
stop_dhcp
sleep 1
start_dhcp
;;
status)
if [ -f "$DHCP_PID_FILE" ]; then
echo "isc-dhcp service is running."
else
echo "isc-dhcp service is not running."
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac
Loading