github.com/cilium/cilium@v1.16.2/pkg/datapath/tables/route.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package tables
     5  
     6  import (
     7  	"encoding/binary"
     8  	"fmt"
     9  	"net/netip"
    10  
    11  	"github.com/cilium/statedb"
    12  	"github.com/cilium/statedb/index"
    13  )
    14  
    15  var (
    16  	RouteIDIndex = statedb.Index[*Route, RouteID]{
    17  		Name: "id",
    18  		FromObject: func(r *Route) index.KeySet {
    19  			return index.NewKeySet(
    20  				RouteID{
    21  					Table:     r.Table,
    22  					LinkIndex: r.LinkIndex,
    23  					Dst:       r.Dst,
    24  				}.Key(),
    25  			)
    26  		},
    27  		FromKey: RouteID.Key,
    28  		Unique:  true,
    29  	}
    30  
    31  	RouteLinkIndex = statedb.Index[*Route, int]{
    32  		Name: "LinkIndex",
    33  		FromObject: func(r *Route) index.KeySet {
    34  			return index.NewKeySet(index.Int(r.LinkIndex))
    35  		},
    36  		FromKey: index.Int,
    37  	}
    38  )
    39  
    40  func NewRouteTable() (statedb.RWTable[*Route], error) {
    41  	return statedb.NewTable(
    42  		"routes",
    43  		RouteIDIndex,
    44  		RouteLinkIndex,
    45  	)
    46  }
    47  
    48  type RouteID struct {
    49  	Table     RouteTable
    50  	LinkIndex int
    51  	Dst       netip.Prefix
    52  }
    53  
    54  func (id RouteID) Key() index.Key {
    55  	key := make([]byte, 0, 4 /* table */ +4 /* link */ +17 /* prefix & bits */)
    56  	key = binary.BigEndian.AppendUint32(key, uint32(id.Table))
    57  	key = binary.BigEndian.AppendUint32(key, uint32(id.LinkIndex))
    58  	addrBytes := id.Dst.Addr().As16()
    59  	key = append(key, addrBytes[:]...)
    60  	return append(key, uint8(id.Dst.Bits()))
    61  }
    62  
    63  type Route struct {
    64  	Table     RouteTable
    65  	LinkIndex int
    66  
    67  	Scope uint8
    68  	Dst   netip.Prefix
    69  	Src   netip.Addr
    70  	Gw    netip.Addr
    71  }
    72  
    73  func (r *Route) DeepCopy() *Route {
    74  	r2 := *r
    75  	return &r2
    76  }
    77  
    78  func (r *Route) String() string {
    79  	return fmt.Sprintf("Route{Dst: %s, Src: %s, Table: %d, LinkIndex: %d}",
    80  		r.Dst, r.Src, r.Table, r.LinkIndex)
    81  }
    82  
    83  func (*Route) TableHeader() []string {
    84  	return []string{
    85  		"Destination",
    86  		"Source",
    87  		"Gateway",
    88  		"LinkIndex",
    89  		"Table",
    90  		"Scope",
    91  	}
    92  }
    93  
    94  func (r *Route) TableRow() []string {
    95  	// Addr.String() shows "invalid IP" for zero value, but here
    96  	// we're expecting absence of IPs, so return empty string for
    97  	// invalid IPs.
    98  	showAddr := func(addr netip.Addr) string {
    99  		if !addr.IsValid() {
   100  			return ""
   101  		}
   102  		return addr.String()
   103  	}
   104  	return []string{
   105  		r.Dst.String(),
   106  		showAddr(r.Src),
   107  		showAddr(r.Gw),
   108  		fmt.Sprintf("%d", r.LinkIndex),
   109  		fmt.Sprintf("%d", r.Table),
   110  		fmt.Sprintf("%d", r.Scope),
   111  	}
   112  }
   113  
   114  func HasDefaultRoute(tbl statedb.Table[*Route], rxn statedb.ReadTxn, linkIndex int) bool {
   115  	// Device has a default route when a route exists in the main table
   116  	// with a zero destination.
   117  	for _, prefix := range []netip.Prefix{zeroPrefixV4, zeroPrefixV6} {
   118  		r, _, _ := tbl.Get(rxn, RouteIDIndex.Query(RouteID{
   119  			RT_TABLE_MAIN,
   120  			linkIndex,
   121  			prefix,
   122  		}))
   123  		if r != nil {
   124  			return true
   125  		}
   126  	}
   127  	return false
   128  }
   129  
   130  var (
   131  	zeroPrefixV4 = netip.PrefixFrom(netip.IPv4Unspecified(), 0)
   132  	zeroPrefixV6 = netip.PrefixFrom(netip.IPv6Unspecified(), 0)
   133  )
   134  
   135  type (
   136  	RouteScope uint8
   137  	RouteTable uint32
   138  )
   139  
   140  // Definitions for route scopes and tables. These are repeated here from the unix
   141  // package to keep the tables package buildable on non-Linux platforms.
   142  const (
   143  	RT_SCOPE_UNIVERSE = RouteScope(0x0)
   144  	RT_SCOPE_SITE     = RouteScope(0xc8)
   145  	RT_SCOPE_LINK     = RouteScope(0xfd)
   146  	RT_SCOPE_HOST     = RouteScope(0xfe)
   147  	RT_SCOPE_NOWHERE  = RouteScope(0xff)
   148  	RT_TABLE_UNSPEC   = RouteTable(0x0)
   149  	RT_TABLE_COMPAT   = RouteTable(0xfc)
   150  	RT_TABLE_DEFAULT  = RouteTable(0xfd)
   151  	RT_TABLE_MAIN     = RouteTable(0xfe)
   152  	RT_TABLE_LOCAL    = RouteTable(0xff)
   153  	RT_TABLE_MAX      = RouteTable(0xffffffff)
   154  )