github.com/vishvananda/netlink@v1.3.1/route.go (about)

     1  package netlink
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strings"
     7  )
     8  
     9  // Scope is an enum representing a route scope.
    10  type Scope uint8
    11  
    12  type NextHopFlag int
    13  
    14  const (
    15  	RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
    16  	RT_FILTER_SCOPE
    17  	RT_FILTER_TYPE
    18  	RT_FILTER_TOS
    19  	RT_FILTER_IIF
    20  	RT_FILTER_OIF
    21  	RT_FILTER_DST
    22  	RT_FILTER_SRC
    23  	RT_FILTER_GW
    24  	RT_FILTER_TABLE
    25  	RT_FILTER_HOPLIMIT
    26  	RT_FILTER_PRIORITY
    27  	RT_FILTER_MARK
    28  	RT_FILTER_MASK
    29  	RT_FILTER_REALM
    30  )
    31  
    32  type Destination interface {
    33  	Family() int
    34  	Decode([]byte) error
    35  	Encode() ([]byte, error)
    36  	String() string
    37  	Equal(Destination) bool
    38  }
    39  
    40  type Encap interface {
    41  	Type() int
    42  	Decode([]byte) error
    43  	Encode() ([]byte, error)
    44  	String() string
    45  	Equal(Encap) bool
    46  }
    47  
    48  // Protocol describe what was the originator of the route
    49  type RouteProtocol int
    50  
    51  // Route represents a netlink route.
    52  type Route struct {
    53  	LinkIndex        int
    54  	ILinkIndex       int
    55  	Scope            Scope
    56  	Dst              *net.IPNet
    57  	Src              net.IP
    58  	Gw               net.IP
    59  	MultiPath        []*NexthopInfo
    60  	Protocol         RouteProtocol
    61  	Priority         int
    62  	Family           int
    63  	Table            int
    64  	Type             int
    65  	Tos              int
    66  	Flags            int
    67  	MPLSDst          *int
    68  	NewDst           Destination
    69  	Encap            Encap
    70  	Via              Destination
    71  	Realm            int
    72  	MTU              int
    73  	MTULock          bool
    74  	Window           int
    75  	Rtt              int
    76  	RttVar           int
    77  	Ssthresh         int
    78  	Cwnd             int
    79  	AdvMSS           int
    80  	Reordering       int
    81  	Hoplimit         int
    82  	InitCwnd         int
    83  	Features         int
    84  	RtoMin           int
    85  	RtoMinLock       bool
    86  	InitRwnd         int
    87  	QuickACK         int
    88  	Congctl          string
    89  	FastOpenNoCookie int
    90  }
    91  
    92  func (r Route) String() string {
    93  	elems := []string{}
    94  	if len(r.MultiPath) == 0 {
    95  		elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex))
    96  	}
    97  	if r.MPLSDst != nil {
    98  		elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst))
    99  	} else {
   100  		elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst))
   101  	}
   102  	if r.NewDst != nil {
   103  		elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst))
   104  	}
   105  	if r.Encap != nil {
   106  		elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
   107  	}
   108  	if r.Via != nil {
   109  		elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
   110  	}
   111  	elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
   112  	if len(r.MultiPath) > 0 {
   113  		elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
   114  	} else {
   115  		elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw))
   116  	}
   117  	elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
   118  	elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
   119  	elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm))
   120  	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
   121  }
   122  
   123  func (r Route) Equal(x Route) bool {
   124  	return r.LinkIndex == x.LinkIndex &&
   125  		r.ILinkIndex == x.ILinkIndex &&
   126  		r.Scope == x.Scope &&
   127  		ipNetEqual(r.Dst, x.Dst) &&
   128  		r.Src.Equal(x.Src) &&
   129  		r.Gw.Equal(x.Gw) &&
   130  		nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
   131  		r.Protocol == x.Protocol &&
   132  		r.Priority == x.Priority &&
   133  		r.Realm == x.Realm &&
   134  		r.Table == x.Table &&
   135  		r.Type == x.Type &&
   136  		r.Tos == x.Tos &&
   137  		r.Hoplimit == x.Hoplimit &&
   138  		r.Flags == x.Flags &&
   139  		(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
   140  		(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
   141  		(r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
   142  		(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
   143  }
   144  
   145  func (r *Route) SetFlag(flag NextHopFlag) {
   146  	r.Flags |= int(flag)
   147  }
   148  
   149  func (r *Route) ClearFlag(flag NextHopFlag) {
   150  	r.Flags &^= int(flag)
   151  }
   152  
   153  type flagString struct {
   154  	f NextHopFlag
   155  	s string
   156  }
   157  
   158  // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
   159  
   160  // NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set:
   161  //   - unix.NLM_F_REPLACE - Replace existing matching config object with this request
   162  //   - unix.NLM_F_EXCL - Don't replace the config object if it already exists
   163  //   - unix.NLM_F_CREATE - Create config object if it doesn't already exist
   164  //   - unix.NLM_F_APPEND - Add to the end of the object list
   165  type RouteUpdate struct {
   166  	Type    uint16
   167  	NlFlags uint16
   168  	Route
   169  }
   170  
   171  type NexthopInfo struct {
   172  	LinkIndex int
   173  	Hops      int
   174  	Gw        net.IP
   175  	Flags     int
   176  	NewDst    Destination
   177  	Encap     Encap
   178  	Via       Destination
   179  }
   180  
   181  func (n *NexthopInfo) String() string {
   182  	elems := []string{}
   183  	elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex))
   184  	if n.NewDst != nil {
   185  		elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst))
   186  	}
   187  	if n.Encap != nil {
   188  		elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
   189  	}
   190  	if n.Via != nil {
   191  		elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
   192  	}
   193  	elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
   194  	elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
   195  	elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
   196  	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
   197  }
   198  
   199  func (n NexthopInfo) Equal(x NexthopInfo) bool {
   200  	return n.LinkIndex == x.LinkIndex &&
   201  		n.Hops == x.Hops &&
   202  		n.Gw.Equal(x.Gw) &&
   203  		n.Flags == x.Flags &&
   204  		(n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
   205  		(n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
   206  }
   207  
   208  type nexthopInfoSlice []*NexthopInfo
   209  
   210  func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
   211  	if len(n) != len(x) {
   212  		return false
   213  	}
   214  	for i := range n {
   215  		if n[i] == nil || x[i] == nil {
   216  			return false
   217  		}
   218  		if !n[i].Equal(*x[i]) {
   219  			return false
   220  		}
   221  	}
   222  	return true
   223  }
   224  
   225  // ipNetEqual returns true iff both IPNet are equal
   226  func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
   227  	if ipn1 == ipn2 {
   228  		return true
   229  	}
   230  	if ipn1 == nil || ipn2 == nil {
   231  		return false
   232  	}
   233  	m1, _ := ipn1.Mask.Size()
   234  	m2, _ := ipn2.Mask.Size()
   235  	return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
   236  }