mirror of
https://github.com/status-im/status-go.git
synced 2025-02-02 09:56:52 +00:00
b2580c79d7
Network disconnect is introduced by removing default gateway, easily reversible condition. On my local machine it takes 30 seconds for peers to reconnect after connectivity is restored. As you guess this is not an accident, and there is 30 seconds timeout for dial expiration. This dial expiration is used in p2p.Server to guarantee that peers are not dialed too often. Additionally I added small script to Makefile to run such tests in docker environment, usage example: ``` make docker-test ARGS="./t/destructive/ -v -network=4" ```
179 lines
4.1 KiB
Go
179 lines
4.1 KiB
Go
package netlink
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
// Scope is an enum representing a route scope.
|
|
type Scope uint8
|
|
|
|
type NextHopFlag int
|
|
|
|
type Destination interface {
|
|
Family() int
|
|
Decode([]byte) error
|
|
Encode() ([]byte, error)
|
|
String() string
|
|
Equal(Destination) bool
|
|
}
|
|
|
|
type Encap interface {
|
|
Type() int
|
|
Decode([]byte) error
|
|
Encode() ([]byte, error)
|
|
String() string
|
|
Equal(Encap) bool
|
|
}
|
|
|
|
// Route represents a netlink route.
|
|
type Route struct {
|
|
LinkIndex int
|
|
ILinkIndex int
|
|
Scope Scope
|
|
Dst *net.IPNet
|
|
Src net.IP
|
|
Gw net.IP
|
|
MultiPath []*NexthopInfo
|
|
Protocol int
|
|
Priority int
|
|
Table int
|
|
Type int
|
|
Tos int
|
|
Flags int
|
|
MPLSDst *int
|
|
NewDst Destination
|
|
Encap Encap
|
|
MTU int
|
|
AdvMSS int
|
|
}
|
|
|
|
func (r Route) String() string {
|
|
elems := []string{}
|
|
if len(r.MultiPath) == 0 {
|
|
elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex))
|
|
}
|
|
if r.MPLSDst != nil {
|
|
elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst))
|
|
} else {
|
|
elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst))
|
|
}
|
|
if r.NewDst != nil {
|
|
elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst))
|
|
}
|
|
if r.Encap != nil {
|
|
elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
|
|
}
|
|
elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
|
|
if len(r.MultiPath) > 0 {
|
|
elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
|
|
} else {
|
|
elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw))
|
|
}
|
|
elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
|
|
elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
|
|
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
|
}
|
|
|
|
func (r Route) Equal(x Route) bool {
|
|
return r.LinkIndex == x.LinkIndex &&
|
|
r.ILinkIndex == x.ILinkIndex &&
|
|
r.Scope == x.Scope &&
|
|
ipNetEqual(r.Dst, x.Dst) &&
|
|
r.Src.Equal(x.Src) &&
|
|
r.Gw.Equal(x.Gw) &&
|
|
nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
|
|
r.Protocol == x.Protocol &&
|
|
r.Priority == x.Priority &&
|
|
r.Table == x.Table &&
|
|
r.Type == x.Type &&
|
|
r.Tos == x.Tos &&
|
|
r.Flags == x.Flags &&
|
|
(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
|
|
(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
|
|
(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
|
|
}
|
|
|
|
func (r *Route) SetFlag(flag NextHopFlag) {
|
|
r.Flags |= int(flag)
|
|
}
|
|
|
|
func (r *Route) ClearFlag(flag NextHopFlag) {
|
|
r.Flags &^= int(flag)
|
|
}
|
|
|
|
type flagString struct {
|
|
f NextHopFlag
|
|
s string
|
|
}
|
|
|
|
// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
|
|
type RouteUpdate struct {
|
|
Type uint16
|
|
Route
|
|
}
|
|
|
|
type NexthopInfo struct {
|
|
LinkIndex int
|
|
Hops int
|
|
Gw net.IP
|
|
Flags int
|
|
NewDst Destination
|
|
Encap Encap
|
|
}
|
|
|
|
func (n *NexthopInfo) String() string {
|
|
elems := []string{}
|
|
elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex))
|
|
if n.NewDst != nil {
|
|
elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst))
|
|
}
|
|
if n.Encap != nil {
|
|
elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
|
|
}
|
|
elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
|
|
elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
|
|
elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
|
|
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
|
}
|
|
|
|
func (n NexthopInfo) Equal(x NexthopInfo) bool {
|
|
return n.LinkIndex == x.LinkIndex &&
|
|
n.Hops == x.Hops &&
|
|
n.Gw.Equal(x.Gw) &&
|
|
n.Flags == x.Flags &&
|
|
(n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
|
|
(n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
|
|
}
|
|
|
|
type nexthopInfoSlice []*NexthopInfo
|
|
|
|
func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
|
|
if len(n) != len(x) {
|
|
return false
|
|
}
|
|
for i := range n {
|
|
if n[i] == nil || x[i] == nil {
|
|
return false
|
|
}
|
|
if !n[i].Equal(*x[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ipNetEqual returns true iff both IPNet are equal
|
|
func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
|
|
if ipn1 == ipn2 {
|
|
return true
|
|
}
|
|
if ipn1 == nil || ipn2 == nil {
|
|
return false
|
|
}
|
|
m1, _ := ipn1.Mask.Size()
|
|
m2, _ := ipn2.Mask.Size()
|
|
return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
|
|
}
|