gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/network/internal/multicast/example_test.go (about) 1 // Copyright 2022 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package multicast_test 16 17 import ( 18 "fmt" 19 "os" 20 "testing" 21 "time" 22 23 "gvisor.dev/gvisor/pkg/buffer" 24 "gvisor.dev/gvisor/pkg/refs" 25 "gvisor.dev/gvisor/pkg/tcpip" 26 "gvisor.dev/gvisor/pkg/tcpip/faketime" 27 "gvisor.dev/gvisor/pkg/tcpip/network/internal/multicast" 28 "gvisor.dev/gvisor/pkg/tcpip/stack" 29 "gvisor.dev/gvisor/pkg/tcpip/testutil" 30 ) 31 32 const ( 33 defaultMinTTL = 10 34 defaultMTU = 1500 35 inputNICID tcpip.NICID = 1 36 outgoingNICID tcpip.NICID = 2 37 ) 38 39 // Example shows how to interact with a multicast RouteTable. 40 func Example() { 41 address := testutil.MustParse4("192.168.1.1") 42 defaultOutgoingInterfaces := []stack.MulticastRouteOutgoingInterface{{ID: outgoingNICID, MinTTL: defaultMinTTL}} 43 routeKey := stack.UnicastSourceAndMulticastDestination{Source: address, Destination: address} 44 multicastRoute := stack.MulticastRoute{inputNICID, defaultOutgoingInterfaces} 45 46 pkt := newPacketBuffer("hello") 47 defer pkt.DecRef() 48 49 clock := faketime.NewManualClock() 50 clock.Advance(10 * time.Second) 51 52 // Create a route table from a specified config. 53 table := multicast.RouteTable{} 54 defer table.Close() 55 config := multicast.DefaultConfig(clock) 56 57 if err := table.Init(config); err != nil { 58 panic(err) 59 } 60 61 // Each entry in the table represents either an installed route or a pending 62 // route. To insert a pending route, call: 63 result, hasBufferSpace := table.GetRouteOrInsertPending(routeKey, pkt) 64 65 // Callers should handle a no buffer space error (e.g. only deliver the 66 // packet locally). 67 if !hasBufferSpace { 68 deliverPktLocally(pkt) 69 } 70 71 // Callers should handle the various pending route states. 72 switch result.GetRouteResultState { 73 case multicast.InstalledRouteFound: 74 // The packet can be forwarded using the installed route. 75 forwardPkt(pkt, result.InstalledRoute) 76 case multicast.NoRouteFoundAndPendingInserted: 77 // The route has just entered the pending state. 78 emitMissingRouteEvent(routeKey) 79 deliverPktLocally(pkt) 80 case multicast.PacketQueuedInPendingRoute: 81 // The route was already in the pending state. 82 deliverPktLocally(pkt) 83 } 84 85 // To transition a pending route to the installed state, call: 86 route := table.NewInstalledRoute(multicastRoute) 87 pendingPackets := table.AddInstalledRoute(routeKey, route) 88 89 // If there was a pending route, then the caller is responsible for 90 // flushing any pending packets. 91 for _, pkt := range pendingPackets { 92 forwardPkt(pkt, route) 93 pkt.DecRef() 94 } 95 96 // To obtain the last used time of the route, call: 97 timestamp, found := table.GetLastUsedTimestamp(routeKey) 98 99 if !found { 100 panic(fmt.Sprintf("table.GetLastUsedTimestamp(%#v) = (_, false)", routeKey)) 101 } 102 103 fmt.Printf("Last used timestamp: %s", timestamp) 104 105 // Finally, to remove an installed route, call: 106 if removed := table.RemoveInstalledRoute(routeKey); !removed { 107 panic(fmt.Sprintf("table.RemoveInstalledRoute(%#v) = false", routeKey)) 108 } 109 110 // Output: 111 // emitMissingRouteEvent 112 // deliverPktLocally 113 // forwardPkt 114 // Last used timestamp: 10000000000 115 } 116 117 func forwardPkt(*stack.PacketBuffer, *multicast.InstalledRoute) { 118 fmt.Println("forwardPkt") 119 } 120 121 func emitMissingRouteEvent(stack.UnicastSourceAndMulticastDestination) { 122 fmt.Println("emitMissingRouteEvent") 123 } 124 125 func deliverPktLocally(*stack.PacketBuffer) { 126 fmt.Println("deliverPktLocally") 127 } 128 129 func newPacketBuffer(body string) *stack.PacketBuffer { 130 return stack.NewPacketBuffer(stack.PacketBufferOptions{ 131 Payload: buffer.MakeWithData([]byte(body)), 132 }) 133 } 134 135 func TestMain(m *testing.M) { 136 refs.SetLeakMode(refs.LeaksPanic) 137 code := m.Run() 138 refs.DoLeakCheck() 139 os.Exit(code) 140 }