44//! Implements an egress stage
55
66use std:: net:: IpAddr ;
7+ #[ allow( unused) ]
78use tracing:: { debug, error, trace, warn} ;
89
9- use net:: eth:: Eth ;
1010use net:: eth:: ethtype:: EthType ;
1111use net:: eth:: mac:: { DestinationMac , SourceMac } ;
1212use net:: {
1313 buffer:: PacketBufferMut ,
1414 headers:: { TryIpv4 , TryIpv6 } ,
1515} ;
16+ use net:: { eth:: Eth , headers:: TryIp } ;
1617
1718use net:: headers:: TryEthMut ;
1819use net:: interface:: InterfaceIndex ;
@@ -131,10 +132,8 @@ impl Egress {
131132 /* do lookup on the adjacency table */
132133 let Some ( adj) = atable. get_adjacency ( addr, ifindex) else {
133134 warn ! ( "{nfi}: missing L2 info for {addr}" ) ;
134-
135- /* Todo: Trigger ARP */
136-
137- packet. done ( DoneReason :: MissL2resolution ) ;
135+ packet. get_meta_mut ( ) . set_need_arp_nd ( true ) ;
136+ packet. done ( DoneReason :: MissL2resolution ) ; // temporary until ARP/ND ready
138137 return None ;
139138 } ;
140139 /* get the mac from the adjacency */
@@ -152,25 +151,23 @@ impl Egress {
152151 }
153152 }
154153
155- fn resolve_next_mac < Buf : PacketBufferMut > (
154+ fn resolve_next_mac_ip < Buf : PacketBufferMut > (
156155 & self ,
157156 ifindex : InterfaceIndex ,
157+ dst_ip : IpAddr ,
158158 packet : & mut Packet < Buf > ,
159159 ) -> Option < DestinationMac > {
160- let nfi = & self . name ;
161160 // if packet was annotated with a next-hop address, try to resolve it using the
162161 // adjacency table. Otherwise, that means that the packet is directly connected
163162 // to us (on the same subnet). So, fetch the destination IP address and try to
164163 // resolve it with the adjacency table as well. If that fails, that's where the
165164 // ARP/ND would need to be triggered.
166- if let Some ( nh_addr) = packet. get_meta ( ) . nh_addr {
167- self . get_adj_mac ( packet, nh_addr, ifindex)
168- } else if let Some ( destination) = packet. ip_destination ( ) {
169- self . get_adj_mac ( packet, destination, ifindex)
165+ let target = if let Some ( nh_addr) = packet. get_meta ( ) . nh_addr {
166+ nh_addr
170167 } else {
171- warn ! ( "{nfi}: could not determine packet destination IP address" ) ;
172- None
173- }
168+ dst_ip
169+ } ;
170+ self . get_adj_mac ( packet , target , ifindex )
174171 }
175172
176173 #[ inline]
@@ -180,11 +177,27 @@ impl Egress {
180177 packet. done ( DoneReason :: RouteFailure ) ;
181178 return ;
182179 } ;
180+ let mut dst_mac = None ;
181+
182+ /* if Ipv4/Ipv6, resolve destination mac. We can't rely on the current Eth mac since
183+ we may have not overwritten it. FIXME(fredi): we should probably do that */
184+ if packet. try_ip ( ) . is_some ( ) {
185+ let Some ( dst_ip) = packet. ip_destination ( ) else {
186+ warn ! ( "Failed to retrieve packet destination IP address" ) ;
187+ packet. done ( DoneReason :: Malformed ) ;
188+ return ;
189+ } ;
190+ /* resolve destination mac */
191+ dst_mac = self . resolve_next_mac_ip ( oif, dst_ip, packet) ;
192+ if dst_mac. is_none ( ) {
193+ warn ! ( "Failed to resolve mac for packet to {dst_ip}" ) ;
194+ return ;
195+ }
196+ }
183197
184- /* resolve destination mac */
185- let Some ( dst_mac) = self . resolve_next_mac ( oif, packet) else {
186- // we could not figure out the destination MAC.
187- // resolve_next_mac() already calls packet.done()
198+ /* if frame is non-ip and we don't know the dst mac, we drop the packet for the time being */
199+ let Some ( dst_mac) = dst_mac else {
200+ packet. done ( DoneReason :: MissL2resolution ) ;
188201 return ;
189202 } ;
190203
0 commit comments