Documentation ¶
Overview ¶
Package multicast contains utilities for supporting multicast routing.
Example ¶
Example shows how to interact with a multicast RouteTable.
package main import ( "fmt" "time" "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/faketime" "gvisor.dev/gvisor/pkg/tcpip/network/internal/multicast" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/testutil" ) const ( defaultMinTTL = 10 inputNICID tcpip.NICID = 1 outgoingNICID tcpip.NICID = 2 ) func main() { address := testutil.MustParse4("192.168.1.1") defaultOutgoingInterfaces := []stack.MulticastRouteOutgoingInterface{{ID: outgoingNICID, MinTTL: defaultMinTTL}} routeKey := stack.UnicastSourceAndMulticastDestination{Source: address, Destination: address} multicastRoute := stack.MulticastRoute{inputNICID, defaultOutgoingInterfaces} pkt := newPacketBuffer("hello") defer pkt.DecRef() clock := faketime.NewManualClock() clock.Advance(10 * time.Second) // Create a route table from a specified config. table := multicast.RouteTable{} defer table.Close() config := multicast.DefaultConfig(clock) if err := table.Init(config); err != nil { panic(err) } // Each entry in the table represents either an installed route or a pending // route. To insert a pending route, call: result, hasBufferSpace := table.GetRouteOrInsertPending(routeKey, pkt) // Callers should handle a no buffer space error (e.g. only deliver the // packet locally). if !hasBufferSpace { deliverPktLocally(pkt) } // Callers should handle the various pending route states. switch result.GetRouteResultState { case multicast.InstalledRouteFound: // The packet can be forwarded using the installed route. forwardPkt(pkt, result.InstalledRoute) case multicast.NoRouteFoundAndPendingInserted: // The route has just entered the pending state. emitMissingRouteEvent(routeKey) deliverPktLocally(pkt) case multicast.PacketQueuedInPendingRoute: // The route was already in the pending state. deliverPktLocally(pkt) } // To transition a pending route to the installed state, call: route := table.NewInstalledRoute(multicastRoute) pendingPackets := table.AddInstalledRoute(routeKey, route) // If there was a pending route, then the caller is responsible for // flushing any pending packets. for _, pkt := range pendingPackets { forwardPkt(pkt, route) pkt.DecRef() } // To obtain the last used time of the route, call: timestamp, found := table.GetLastUsedTimestamp(routeKey) if !found { panic(fmt.Sprintf("table.GetLastUsedTimestamp(%#v) = (_, false)", routeKey)) } fmt.Printf("Last used timestamp: %s", timestamp) // Finally, to remove an installed route, call: if removed := table.RemoveInstalledRoute(routeKey); !removed { panic(fmt.Sprintf("table.RemoveInstalledRoute(%#v) = false", routeKey)) } } func forwardPkt(*stack.PacketBuffer, *multicast.InstalledRoute) { fmt.Println("forwardPkt") } func emitMissingRouteEvent(stack.UnicastSourceAndMulticastDestination) { fmt.Println("emitMissingRouteEvent") } func deliverPktLocally(*stack.PacketBuffer) { fmt.Println("deliverPktLocally") } func newPacketBuffer(body string) *stack.PacketBuffer { return stack.NewPacketBuffer(stack.PacketBufferOptions{ Payload: buffer.MakeWithData([]byte(body)), }) }
Output: emitMissingRouteEvent deliverPktLocally forwardPkt Last used timestamp: 10000000000
Index ¶
- Constants
- Variables
- type Config
- type GetRouteResult
- type GetRouteResultState
- type InstalledRoute
- type PendingRoute
- type RouteTable
- func (r *RouteTable) AddInstalledRoute(key stack.UnicastSourceAndMulticastDestination, route *InstalledRoute) []*stack.PacketBuffer
- func (r *RouteTable) Close()
- func (r *RouteTable) GetLastUsedTimestamp(key stack.UnicastSourceAndMulticastDestination) (tcpip.MonotonicTime, bool)
- func (r *RouteTable) GetRouteOrInsertPending(key stack.UnicastSourceAndMulticastDestination, pkt *stack.PacketBuffer) (GetRouteResult, bool)
- func (r *RouteTable) Init(config Config) error
- func (r *RouteTable) NewInstalledRoute(route stack.MulticastRoute) *InstalledRoute
- func (r *RouteTable) RemoveAllInstalledRoutes()
- func (r *RouteTable) RemoveInstalledRoute(key stack.UnicastSourceAndMulticastDestination) bool
Examples ¶
Constants ¶
const ( // DefaultMaxPendingQueueSize corresponds to the number of elements that can // be in the packet queue for a pending route. // // Matches the Linux default queue size: // https://github.com/torvalds/linux/blob/26291c54e11/net/ipv6/ip6mr.c#L1186 DefaultMaxPendingQueueSize uint8 = 3 // DefaultPendingRouteExpiration is the default maximum lifetime of a pending // route. // // Matches the Linux default: // https://github.com/torvalds/linux/blob/26291c54e11/net/ipv6/ip6mr.c#L991 DefaultPendingRouteExpiration time.Duration = 10 * time.Second // DefaultCleanupInterval is the default frequency of the routine that // expires pending routes. // // Matches the Linux default: // https://github.com/torvalds/linux/blob/26291c54e11/net/ipv6/ip6mr.c#L793 DefaultCleanupInterval time.Duration = 10 * time.Second )
Variables ¶
var ( // ErrNoBufferSpace indicates that no buffer space is available in the // pending route packet queue. ErrNoBufferSpace = errors.New("unable to queue packet, no buffer space available") // ErrMissingClock indicates that a clock was not provided as part of the // Config, but is required. ErrMissingClock = errors.New("clock must not be nil") // ErrAlreadyInitialized indicates that RouteTable.Init was already invoked. ErrAlreadyInitialized = errors.New("table is already initialized") )
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct { // MaxPendingQueueSize corresponds to the maximum number of queued packets // for a pending route. // // If the caller attempts to queue a packet and the queue already contains // MaxPendingQueueSize elements, then the packet will be rejected and should // not be forwarded. MaxPendingQueueSize uint8 // Clock represents the clock that should be used to obtain the current time. // // This field is required and must have a non-nil value. Clock tcpip.Clock }
Config represents the options for configuring a RouteTable.
+stateify savable
func DefaultConfig ¶
DefaultConfig returns the default configuration for the table.
type GetRouteResult ¶
type GetRouteResult struct { // GetRouteResultState signals the result of calling GetRouteOrInsertPending. GetRouteResultState GetRouteResultState // InstalledRoute represents the existing installed route. This field will // only be populated if the GetRouteResultState is InstalledRouteFound. InstalledRoute *InstalledRoute }
GetRouteResult represents the result of calling GetRouteOrInsertPending.
type GetRouteResultState ¶
type GetRouteResultState uint8
GetRouteResultState signals the result of calling GetRouteOrInsertPending.
const ( // InstalledRouteFound indicates that an InstalledRoute was found. InstalledRouteFound GetRouteResultState = iota // PacketQueuedInPendingRoute indicates that the packet was queued in an // existing pending route. PacketQueuedInPendingRoute // NoRouteFoundAndPendingInserted indicates that no route was found and that // a pending route was newly inserted into the RouteTable. NoRouteFoundAndPendingInserted )
func (GetRouteResultState) String ¶
func (e GetRouteResultState) String() string
type InstalledRoute ¶
type InstalledRoute struct { stack.MulticastRoute // contains filtered or unexported fields }
InstalledRoute represents a route that is in the installed state.
If a route is in the installed state, then it may be used to forward multicast packets.
+stateify savable
func (*InstalledRoute) LastUsedTimestamp ¶
func (r *InstalledRoute) LastUsedTimestamp() tcpip.MonotonicTime
LastUsedTimestamp returns a monotonic timestamp that corresponds to the last time the route was used or updated.
func (*InstalledRoute) SetLastUsedTimestamp ¶
func (r *InstalledRoute) SetLastUsedTimestamp(monotonicTime tcpip.MonotonicTime)
SetLastUsedTimestamp sets the time that the route was last used.
The timestamp is only updated if it occurs after the currently set timestamp. Callers should invoke this anytime the route is used to forward a packet.
type PendingRoute ¶
type PendingRoute struct {
// contains filtered or unexported fields
}
PendingRoute represents a route that is in the "pending" state.
A route is in the pending state if an installed route does not yet exist for the entry. For such routes, packets are added to an expiring queue until a route is installed.
+stateify savable
type RouteTable ¶
type RouteTable struct {
// contains filtered or unexported fields
}
RouteTable represents a multicast routing table.
+stateify savable
func (*RouteTable) AddInstalledRoute ¶
func (r *RouteTable) AddInstalledRoute(key stack.UnicastSourceAndMulticastDestination, route *InstalledRoute) []*stack.PacketBuffer
AddInstalledRoute adds the provided route to the table.
Packets that were queued while the route was in the pending state are returned. The caller assumes ownership of these packets and is responsible for forwarding and releasing them. If an installed route already exists for the provided key, then it is overwritten.
func (*RouteTable) Close ¶
func (r *RouteTable) Close()
Close cleans up resources held by the table.
Calling this will stop the cleanup routine and release any packets owned by the table.
func (*RouteTable) GetLastUsedTimestamp ¶
func (r *RouteTable) GetLastUsedTimestamp(key stack.UnicastSourceAndMulticastDestination) (tcpip.MonotonicTime, bool)
GetLastUsedTimestamp returns a monotonic timestamp that represents the last time the route that matches the provided key was used or updated.
Returns true if a matching route was found. Otherwise returns false.
func (*RouteTable) GetRouteOrInsertPending ¶
func (r *RouteTable) GetRouteOrInsertPending(key stack.UnicastSourceAndMulticastDestination, pkt *stack.PacketBuffer) (GetRouteResult, bool)
GetRouteOrInsertPending attempts to fetch the installed route that matches the provided key.
If no matching installed route is found, then the pkt is cloned and queued in a pending route. The GetRouteResult.GetRouteResultState will indicate whether the pkt was queued in a new pending route or an existing one.
If the relevant pending route queue is at max capacity, then returns false. Otherwise, returns true.
func (*RouteTable) Init ¶
func (r *RouteTable) Init(config Config) error
Init initializes the RouteTable with the provided config.
An error is returned if the config is not valid.
Must be called before any other function on the table.
func (*RouteTable) NewInstalledRoute ¶
func (r *RouteTable) NewInstalledRoute(route stack.MulticastRoute) *InstalledRoute
NewInstalledRoute instantiates an installed route for the table.
func (*RouteTable) RemoveAllInstalledRoutes ¶
func (r *RouteTable) RemoveAllInstalledRoutes()
RemoveAllInstalledRoutes removes all installed routes from the table.
func (*RouteTable) RemoveInstalledRoute ¶
func (r *RouteTable) RemoveInstalledRoute(key stack.UnicastSourceAndMulticastDestination) bool
RemoveInstalledRoute deletes any installed route that matches the provided key.
Returns true if a route was removed. Otherwise returns false.