mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-07 05:40:52 +08:00
fix bug: udp write 提供了对外封装的Write()
表现为一个阻塞操作,如果本地arp缓存失效,就会重新发起一次arp广播,更新目标ip地址的MAC 更新后将再次尝试写数据
This commit is contained in:
@@ -184,10 +184,17 @@ func (conn *UdpConn) Read(rcv []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *UdpConn) Write(snd []byte) {
|
func (conn *UdpConn) Write(snd []byte) error {
|
||||||
_, _, err := conn.ep.Write(tcpip.SlicePayload(snd), tcpip.WriteOptions{To: &conn.raddr})
|
for {
|
||||||
|
_, notifyCh, err := conn.ep.Write(tcpip.SlicePayload(snd), tcpip.WriteOptions{To: &conn.raddr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
if err == tcpip.ErrNoLinkAddress {
|
||||||
|
<-notifyCh
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s", err.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -151,7 +151,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.
|
|||||||
copy(h.HardwareAddressSender(), linkEP.LinkAddress())
|
copy(h.HardwareAddressSender(), linkEP.LinkAddress())
|
||||||
copy(h.ProtocolAddressSender(), localAddr)
|
copy(h.ProtocolAddressSender(), localAddr)
|
||||||
copy(h.ProtocolAddressTarget(), addr)
|
copy(h.ProtocolAddressTarget(), addr)
|
||||||
|
log.Println("arp发起广播 寻找:", addr)
|
||||||
return linkEP.WritePacket(r, hdr, buffer.VectorisedView{}, ProtocolNumber)
|
return linkEP.WritePacket(r, hdr, buffer.VectorisedView{}, ProtocolNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -201,7 +201,8 @@ func (c *linkAddrCache) makeAndAddEntry(k tcpip.FullAddress, v tcpip.LinkAddress
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get reports any known link address for k.
|
// get reports any known link address for k.
|
||||||
func (c *linkAddrCache) get(k tcpip.FullAddress, linkRes LinkAddressResolver, localAddr tcpip.Address, linkEP LinkEndpoint, waker *sleep.Waker) (tcpip.LinkAddress, <-chan struct{}, *tcpip.Error) {
|
func (c *linkAddrCache) get(k tcpip.FullAddress, linkRes LinkAddressResolver,
|
||||||
|
localAddr tcpip.Address, linkEP LinkEndpoint, waker *sleep.Waker) (tcpip.LinkAddress, <-chan struct{}, *tcpip.Error) {
|
||||||
log.Println("在arp本地缓存中寻找", k)
|
log.Println("在arp本地缓存中寻找", k)
|
||||||
if linkRes != nil {
|
if linkRes != nil {
|
||||||
if addr, ok := linkRes.ResolveStaticAddress(k.Addr); ok {
|
if addr, ok := linkRes.ResolveStaticAddress(k.Addr); ok {
|
||||||
@@ -214,7 +215,7 @@ func (c *linkAddrCache) get(k tcpip.FullAddress, linkRes LinkAddressResolver, lo
|
|||||||
// 尝试从缓存中得到MAC地址
|
// 尝试从缓存中得到MAC地址
|
||||||
if entry, ok := c.cache[k]; ok {
|
if entry, ok := c.cache[k]; ok {
|
||||||
switch s := entry.state(); s {
|
switch s := entry.state(); s {
|
||||||
case expired:
|
case expired: // 过期了
|
||||||
case ready:
|
case ready:
|
||||||
return entry.linkAddr, nil, nil
|
return entry.linkAddr, nil, nil
|
||||||
case failed:
|
case failed:
|
||||||
@@ -251,7 +252,8 @@ func (c *linkAddrCache) removeWaker(k tcpip.FullAddress, waker *sleep.Waker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linkAddrCache) startAddressResolution(k tcpip.FullAddress, linkRes LinkAddressResolver, localAddr tcpip.Address, linkEP LinkEndpoint, done <-chan struct{}) {
|
func (c *linkAddrCache) startAddressResolution(k tcpip.FullAddress, linkRes LinkAddressResolver,
|
||||||
|
localAddr tcpip.Address, linkEP LinkEndpoint, done <-chan struct{}) {
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
// Send link request, then wait for the timeout limit and check
|
// Send link request, then wait for the timeout limit and check
|
||||||
// whether the request succeeded.
|
// whether the request succeeded.
|
||||||
|
@@ -13,7 +13,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// ageLimit is set to the same cache stale time used in Linux.
|
// ageLimit is set to the same cache stale time used in Linux.
|
||||||
ageLimit = 1 * time.Minute
|
//ageLimit = 1 * time.Minute
|
||||||
|
ageLimit = 5 * time.Second
|
||||||
// resolutionTimeout is set to the same ARP timeout used in Linux.
|
// resolutionTimeout is set to the same ARP timeout used in Linux.
|
||||||
resolutionTimeout = 1 * time.Second
|
resolutionTimeout = 1 * time.Second
|
||||||
// resolutionAttempts is set to the same ARP retries used in Linux.
|
// resolutionAttempts is set to the same ARP retries used in Linux.
|
||||||
|
Reference in New Issue
Block a user