github.com/vishvananda/netlink@v1.3.0/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  	Window           int
    74  	Rtt              int
    75  	RttVar           int
    76  	Ssthresh         int
    77  	Cwnd             int
    78  	AdvMSS           int
    79  	Reordering       int
    80  	Hoplimit         int
    81  	InitCwnd         int
    82  	Features         int
    83  	RtoMin           int
    84  	InitRwnd         int
    85  	QuickACK         int
    86  	Congctl          string
    87  	FastOpenNoCookie int
    88  }
    89  
    90  func (r Route) String() string {
    91  	elems := []string{}
    92  	if len(r.MultiPath) == 0 {
    93  		elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex))
    94  	}
    95  	if r.MPLSDst != nil {
    96  		elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst))
    97  	} else {
    98  		elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst))
    99  	}
   100  	if r.NewDst != nil {
   101  		elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst))
   102  	}
   103  	if r.Encap != nil {
   104  		elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
   105  	}
   106  	if r.Via != nil {
   107  		elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
   108  	}
   109  	elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
   110  	if len(r.MultiPath) > 0 {
   111  		elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
   112  	} else {
   113  		elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw))
   114  	}
   115  	elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
   116  	elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
   117  	elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm))
   118  	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
   119  }
   120  
   121  func (r Route) Equal(x Route) bool {
   122  	return r.LinkIndex == x.LinkIndex &&
   123  		r.ILinkIndex == x.ILinkIndex &&
   124  		r.Scope == x.Scope &&
   125  		ipNetEqual(r.Dst, x.Dst) &&
   126  		r.Src.Equal(x.Src) &&
   127  		r.Gw.Equal(x.Gw) &&
   128  		nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
   129  		r.Protocol == x.Protocol &&
   130  		r.Priority == x.Priority &&
   131  		r.Realm == x.Realm &&
   132  		r.Table == x.Table &&
   133  		r.Type == x.Type &&
   134  		r.Tos == x.Tos &&
   135  		r.Hoplimit == x.Hoplimit &&
   136  		r.Flags == x.Flags &&
   137  		(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
   138  		(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
   139  		(r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
   140  		(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
   141  }
   142  
   143  func (r *Route) SetFlag(flag NextHopFlag) {
   144  	r.Flags |= int(flag)
   145  }
   146  
   147  func (r *Route) ClearFlag(flag NextHopFlag) {
   148  	r.Flags &^= int(flag)
   149  }
   150  
   151  type flagString struct {
   152  	f NextHopFlag
   153  	s string
   154  }
   155  
   156  // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
   157  
   158  // NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set:
   159  //   - unix.NLM_F_REPLACE - Replace existing matching config object with this request
   160  //   - unix.NLM_F_EXCL - Don't replace the config object if it already exists
   161  //   - unix.NLM_F_CREATE - Create config object if it doesn't already exist
   162  //   - unix.NLM_F_APPEND - Add to the end of the object list
   163  type RouteUpdate struct {
   164  	Type    uint16
   165  	NlFlags uint16
   166  	Route
   167  }
   168  
   169  type NexthopInfo struct {
   170  	LinkIndex int
   171  	Hops      int
   172  	Gw        net.IP
   173  	Flags     int
   174  	NewDst    Destination
   175  	Encap     Encap
   176  	Via       Destination
   177  }
   178  
   179  func (n *NexthopInfo) String() string {
   180  	elems := []string{}
   181  	elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex))
   182  	if n.NewDst != nil {
   183  		elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst))
   184  	}
   185  	if n.Encap != nil {
   186  		elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
   187  	}
   188  	if n.Via != nil {
   189  		elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
   190  	}
   191  	elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
   192  	elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
   193  	elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
   194  	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
   195  }
   196  
   197  func (n NexthopInfo) Equal(x NexthopInfo) bool {
   198  	return n.LinkIndex == x.LinkIndex &&
   199  		n.Hops == x.Hops &&
   200  		n.Gw.Equal(x.Gw) &&
   201  		n.Flags == x.Flags &&
   202  		(n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
   203  		(n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
   204  }
   205  
   206  type nexthopInfoSlice []*NexthopInfo
   207  
   208  func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
   209  	if len(n) != len(x) {
   210  		return false
   211  	}
   212  	for i := range n {
   213  		if n[i] == nil || x[i] == nil {
   214  			return false
   215  		}
   216  		if !n[i].Equal(*x[i]) {
   217  			return false
   218  		}
   219  	}
   220  	return true
   221  }
   222  
   223  // ipNetEqual returns true iff both IPNet are equal
   224  func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
   225  	if ipn1 == ipn2 {
   226  		return true
   227  	}
   228  	if ipn1 == nil || ipn2 == nil {
   229  		return false
   230  	}
   231  	m1, _ := ipn1.Mask.Size()
   232  	m2, _ := ipn2.Mask.Size()
   233  	return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
   234  }