前情提要——
 smoltcp路由规则 
Iface poll的时候,会对socket集中的每个socket检查是否写入或读出。这里对写入(socket_egress)的情况进行分析。socket_egress会对所有的active的socket进行dispatch ip,也就是加上ip头和链路头。此时会先对目标ip进行分析,查看其是否在自己的neighbor cache里,在就直接封装进链路头然后就可以发送了,如果不在就会发送arp来确认mac。接受到arp rply后就把其装进cache。可是cache的容量就4,是否意味着需要频繁的发送arp。
 
cache是可以调的,要在编译时加参数,见 GitHub - smoltcp-rs/smoltcp: a smol tcp/ip stack 
Configuration 
smoltcp  has some configuration settings that are set at compile time, affecting sizesand counts of buffers.
They can be set in two ways:
Via Cargo features: enable a feature like <name>-<value>. name must be in lowercase and use dashes instead of underscores. For example. iface-max-addr-count-3. Only a selection of values is available, check Cargo.toml for the list.
 
Via environment variables at build time: set the variable named SMOLTCP_<value>. For example SMOLTCP_IFACE_MAX_ADDR_COUNT=3 cargo build. You can also set them in the [env] section of .cargo/config.toml. Any value can be set, unlike with Cargo features.
 
 
Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting with different values, compilation fails.
 
 
现在尝试给loopback的iface添加多个ip,但是仅有127.0.0.1会响应Arp、存入cache中,而其他的不会:
RECVFROM不返回,不知道为啥
 
 
当绑定同一个ip时是可以接收到的:
 
绑了另外一个ip后:
    let socket = UdpSocket::bind("127.0.0.1:34254")?;
    socket.connect("127.0.0.2:34254")?;
    let listener = UdpSocket::bind("127.0.0.2:34254")?;
    let msg = "Hello, loopback!";
    socket.send(msg.as_bytes())?;
    let mut buf = [0; 1024];
    let (amt, _src) = listener.recv_from(&mut buf)?;
 
 
             
            
               
               
               
            
           
          
            
            
               smoltcp如何选择发包网卡 
从smoltcp loopback demo产生疑问  
观察到 socket set 与 iface 是分离的,在smoltcp中创建的socket set直接在对应iface下poll https://code.dragonos.org.cn/xref/smoltcp-0.9.1/examples/loopback.rs#117 :
117      let mut sockets: [_; 2] = Default::default();
118      let mut sockets = SocketSet::new(&mut sockets[..]);
119      let server_handle = sockets.add(server_socket);
120      let client_handle = sockets.add(client_socket);
121  
122      let mut did_listen = false;
123      let mut did_connect = false;
124      let mut done = false;
125      while !done && clock.elapsed() < Instant::from_millis(10_000) {
126          iface.poll(clock.elapsed(), &mut device, &mut sockets);
 
再参考DragonOS下关于socket接收到信息的回调过程 https://code.dragonos.org.cn/xref/DragonOS-0.1.9/kernel/src/net/net_core.rs#122 :
122 pub fn poll_ifaces() {
123     let guard = NET_DRIVERS.read_irqsave();
124     if guard.len() == 0 {
125         kwarn!("poll_ifaces: No net driver found!");
126         return;
127     }
128     let mut sockets = SOCKET_SET.lock_irqsave();
129     for (_, iface) in guard.iter() {
130         iface.poll(&mut sockets).ok();
131     }
132     let _ = send_event(&sockets);
133 }
 
             
            
               
               
               
            
           
          
            
            
              好像没什么问题了。主要是,在链路层传输时,譬如loopback网卡ping自己127.0.0.1时,即使已经知道自己ip为127.0.0.1,仍然要进行一次ARP,以获取自己的mac地址到邻居地址缓存(neighbor cache)中,这个行为比较奇怪(但不影响)
             
            
               
               
               
            
           
          
            
            
              不过还有一个问题,linux内核中,路由是有单独一个子系统的,但在smoltcp的设计中,路由和iface系统是在一块的。因此继续沿用smoltcp、netdevice还要添加上路由的接口。
             
            
               
               
               
            
           
          
            
            
              没道理的,怎么可能127.0.0.2不在127.0.0.1~8/8的cidr下?
  
  
    
    
      
              return None; 
          } 
           
          // Discard packets with non-unicast source addresses. 
          if !source_protocol_addr.is_unicast() || !source_hardware_addr.is_unicast() { 
              net_debug!("arp: non-unicast source address"); 
              return None; 
          } 
           
          if !self.in_same_network(&IpAddress::Ipv4(source_protocol_addr)) { 
              net_debug!("arp: source IP address not in same network as us"); 
              return None; 
          } 
           
          // Fill the ARP cache from any ARP packet aimed at us (both request or response). 
          // We fill from requests too because if someone is requesting our address they 
          // are probably going to talk to us, so we avoid having to request their address 
          // when we later reply to them. 
          self.neighbor_cache.fill( 
              source_protocol_addr.into(), 
              source_hardware_addr.into(), 
       
     
   
  
    
    
  
  
 
  
  
    
    
      
                          let mut packet = ArpPacket::new_unchecked(frame.payload_mut()); 
                          arp_repr.emit(&mut packet); 
                      }) 
                  } 
                  EthernetPacket::Ip(packet) => { 
                      self.dispatch_ip(tx_token, PacketMeta::default(), packet, frag) 
                  } 
              } 
          } 
           
          fn in_same_network(&self, addr: &IpAddress) -> bool { 
              self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr)) 
          } 
           
          fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> { 
              // Send directly. 
              // note: no need to use `self.is_broadcast()` to check for subnet-local broadcast addrs 
              //       here because `in_same_network` will already return true. 
              if self.in_same_network(addr) || addr.is_broadcast() { 
                  return Some(*addr); 
              } 
       
     
   
  
    
    
  
  
 
除非发包网卡有问题,或者说是socket poll的过程有问题
             
            
               
               
               
            
           
          
            
            
               UdpSocket发包问题 
尝试在os使用udpsocket bind 12580端口,然后在本机使用udpsocket连接无线网卡ip的12580端口,并发送数据给该端口。
表现:os接受到数据,但是无法往本机发数据。
             
            
               
               
               
            
           
          
            
            
              不断调试发现,问题在于如果访问外部ip,不会主动发送arp,导致发包错误。似乎外部ip主动发送数据到dragon时,dragon做出response会发出arp,则后续向该ip可以建立通信;如果是dragon主动第一次向某外部ip发包,则不会触发发送arp?