DHCP relay , unicast request and HW offload

HI,

I’m having the following topology:

[ hAP ax2/ac2 ] — [ CRS328-24P-4S+ ] — [ RB450Gx4 ]

  • hAPs are acting as AP/bridges (no L3). There are several VLANs on them, each w/ different SSID

  • CRS is acting as switch/L3 router and DHCP relay. HW offloading and L3 routing is enabled here between above VLANS

  • RB450 is acting as DHCP server and Internet GW

So basic DHCP works. Clients are getting IP addresses and they are keeping them. However when I enable debug on DHCP server I’m seeing a lot of

2025-10-03 12:11:26 dhcp,debug received request from 78:8C:77:C2:XX:XX with unknown giaddr 0.0.0.0

Sniffer launched on DHCP server interfaces shows that those events are triggered by the unicast packets between DHCP client and DHCP server with DHCP REQUEST inside (after half of lease time has passed). Since those packets are ignored by RB450, at some point the DHCP client falls back to DHCP REQUEST sent towards broadcast. At this point DHCP server accepts the request and extends the DHCP lease.

What I think is happening under the hood:

  • the broadcast DHCP packets are handled via switch CPU and giaddr field is populated (as expected from the DHCP relay)
  • the unicast packets are offloaded and are bypassing CPU and nogiaddr field is populated (thus 0.0.0.0 )
  • since DHCP server is expecting in each renewal the giaddr field populated, it treats DHCP REQUESTs as invalid packets.

Important config parts:

DHCP RELAY:

/ip dhcp-relay
add dhcp-server=192.168.XX.5 disabled=no interface=vl100 local-address=192.168.AA.254
local-address-as-src-ip=yes name=user
add dhcp-server=192.168.XX.5 disabled=no interface=vl102 local-address=192.168.BB.254
local-address-as-src-ip=yes name=srv
add dhcp-server=192.168.XX.5 disabled=no interface=vl230 local-address=192.168.CC.254
local-address-as-src-ip=yes name=iot

DHCP SERVER:

/ip dhcp-server
add address-pool=user interface=vl300 lease-time=4h name=user relay=192.168.AA.254
add address-pool=srv interface=vl300 lease-time=4h name=srv relay=192.168.BB.254
add address-pool=iot interface=vl300 lease-time=4h name=iot relay=192.168.CC.254

Question: I’m thinking correctly here? What are my options (without disabling HW offload on the switch). It looks like some sort of MT bug to be honest.

Could you use a switch rule to punt matching packets to CPU to see if that helps?
Something like this?
It might at least prove/disprove your idea about it not working because it bypasses the CPU. You could also temporarily disable L3HWOffload to prove a point...or not.

/interface ethernet switch rule
add dst-port=67 protocol=udp redirect-to-cpu=yes switch=switch1

I’ve tried that but that rule alone does not work (as expected). Packet gets dropped for some reason.

I believe I need to add either /interface/bridge/nat add action=redirect... or /ip firewall nat add action=redirect...but I couldn’t find any documentation why that part is needed. ( see switch - rule - redirect to cpu issue? )

Although this is a home infrastructure its treated as production environment (we work from home) so disruptive config changes can be done in “maintenance window” :slight_smile: (next weekend most likely).

So I’m mostly interested if someone encountered similar behavior or if my way of thinking is correct.

I'll be honest, I'd be stabbing in the dark at that point. I've got switch rules succesfully dropping traffic by setting the destination ports as null but haven't gathered the will to do battle and improve it so that it can be logged as dropped rather than just silently dropped.

For anyone in the future that will be affected by this issue:

As disabling HW offload was not an option I’ve came up w/ alternative approach.

Instead of single DHCP interface with different relay values (old config):

/ip dhcp-server
add address-pool=cctv interface=vl300 lease-time=4h name=vl_cctv relay=192.168.xx.254
add address-pool=iot interface=vl300 lease-time=4h name=vl_iot relay=192.168.xx.254
add address-pool=srv interface=vl300 lease-time=4h name=vl_srv relay=192.168.xx.254
add address-pool=user interface=vl300 lease-time=4h name=vl_user relay=192.168.xx.254

I’ve made the IP mask between the switch and DHCP server shorter (/24 instead of /30) then used macvlan interfaces and set relay to magic value 255.255.255.255 (any address). So now each DHCP pool is using different interface (new config below):

/interface macvlan
add interface=vl310 mac-address=02:A1:B7:1F:ZZ:ZZ name=mac_cctv
add interface=vl310 mac-address=DA:E9:35:25:ZZ:ZZ name=mac_iot
add interface=vl310 mac-address=C6:AE:07:98:ZZ:ZZ name=mac_srv
add interface=vl310 mac-address=52:BA:5A:F5:ZZ:ZZ name=mac_user

/ip address
add address=192.168.XX.A1/24 interface=mac_iot network=192.168.XX.0
add address=192.168.XX.A2/24 interface=mac_cctv network=192.168.XX.0
add address=192.168.XX.A3/24 interface=mac_srv network=192.168.XX.0
add address=192.168.XX.A4/24 interface=mac_user network=192.168.XX.0

/ip dhcp-server
add address-pool=cctv interface=mac_cctv lease-time=4h name=mac_cctv relay=255.255.255.255
add address-pool=iot interface=mac_iot lease-time=4h name=mac_iot relay=255.255.255.255
add address-pool=srv interface=mac_srv lease-time=4h name=mac_srv relay=255.255.255.255
add address-pool=user interface=mac_user lease-time=4h name=mac_user relay=255.255.255.255

I’ve also changed thedhcp-relayconfiguration on the switch to point different IP’s depending on VLAN:

/ip dhcp-relay
add dhcp-server=192.168.XX.A1 disabled=no interface=vl240 local-address=192.168.XX.254 name=mac_cctv
add dhcp-server=192.168.XX.A2 disabled=no interface=vl230 local-address=192.168.XX.254 name=mac_iot
add dhcp-server=192.168.XX.A3 disabled=no interface=vl102 local-address=192.168.XX.254 name=mac_srv
add dhcp-server=192.168.XX.A4 disabled=no interface=vl100 local-address=192.168.XX.254 name=mac_user

So far it works. So I hope this might be useful till issue get fixed.