diff options
Diffstat (limited to 'pkg/tcpip/link/gre/gre.go')
-rw-r--r-- | pkg/tcpip/link/gre/gre.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/pkg/tcpip/link/gre/gre.go b/pkg/tcpip/link/gre/gre.go index 254a1b4d6..38d281e86 100644 --- a/pkg/tcpip/link/gre/gre.go +++ b/pkg/tcpip/link/gre/gre.go @@ -1,11 +1,18 @@ package gre import ( + "context" "log" "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/buffer" + "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/channel" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/stack" + "gvisor.dev/gvisor/pkg/tcpip/transport/gre" + "gvisor.dev/gvisor/pkg/tcpip/transport/raw" + "gvisor.dev/gvisor/pkg/waiter" ) var SIZE = 16 @@ -36,3 +43,111 @@ func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { e.Endpoint.Attach(dispatcher) } + +type GrePacketInfo struct { + pi *channel.PacketInfo +} + +func (g GrePacketInfo) FullPayload() ([]byte, *tcpip.Error){ + log.Println("FullPayload") + pkt := g.pi.Pkt + size := pkt.Size() + vv := buffer.NewVectorisedView(size, pkt.Views()) + var buf = make([]byte, size, size) + pos := 0 + for { + copied, err := vv.Read(buf[pos:]) + log.Printf("VectorisedView Read: %d %d %d %v", size, pos, copied, err) + if err != nil { + return nil, tcpip.ErrBadBuffer + } + pos = pos + copied + if pos == size { + break + } + } + + log.Printf("FullPayload return: %d %v", len(buf), buf) + return buf, nil +} + +func (g GrePacketInfo) Payload(size int) ([]byte, *tcpip.Error){ + log.Println("Payload") + return nil, tcpip.ErrNotSupported +} + +type GreHandlerInfo struct { + ChEp *channel.Endpoint + Raw tcpip.Endpoint + Raddr tcpip.FullAddress +} + +func (info *GreHandlerInfo) greHandler(req *gre.ForwarderRequest) { + pkt := req.Pkt + log.Println("greHandler: ", req.Pkt.Size(), req.Pkt.Views()) + greHdr := header.GRE(pkt.TransportHeader().View()) + proto := greHdr.ProtocolType() + views := pkt.Data.Views() + size := pkt.Data.Size() + data := buffer.NewVectorisedView(size, views) + newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ + Data: data, + }) + log.Printf("greHandler proto: %d cloned: %v", proto, newPkt.Views()) + + info.ChEp.InjectInbound(proto, newPkt) +} + +func (info *GreHandlerInfo) greRead(ep *channel.Endpoint) { + for { + pi, err := ep.ReadContext(context.Background()); + linkHdr := pi.Pkt.LinkHeader() + greHdr := header.GRE(linkHdr.Push(header.GREHeaderSize)) + greHdr.SetProtocolType(pi.Proto) + log.Printf("greRead %d %v %v %v", pi.Proto, pi, err, greHdr) + opts := tcpip.WriteOptions{ + //To: &info.Raddr + } + info.Raw.Write(GrePacketInfo{&pi}, opts) + } +} + +func (e *Endpoint) Start(s *stack.Stack, laddr, raddr *tcpip.Address) { + // Create TCP endpoint. + var rawWq waiter.Queue + rawEp, tcperr := raw.NewEndpoint(s, ipv4.ProtocolNumber, header.GREProtocolNumber, &rawWq) + if tcperr != nil { + log.Fatal(tcperr) + } + log.Println("EP: %s", rawEp) + + fraddr := tcpip.FullAddress{NIC: 1, Addr: *raddr} + flAddr := tcpip.FullAddress{NIC: 1, Addr: *laddr} + tcperr = rawEp.Bind(flAddr) + if tcperr != nil { + log.Fatal(tcperr) + } + log.Printf("Remote: %v %v", raddr, fraddr) + + // Create GRE + // greEP := grelink.New(mtu - 24) + chEP := e.GetChannel() + // TODO detect IPv4/IPv6 + e.NMaxHeaderLength = header.IPv6FixedHeaderSize + header.GREHeaderSize + + greInfo := GreHandlerInfo{ +// Ep: loEP, + ChEp: chEP, + Raw: rawEp, + Raddr: fraddr, + } + greFwd := gre.NewForwarder(s, greInfo.greHandler) + s.SetTransportProtocolHandler(header.GREProtocolNumber, greFwd.HandlePacket) + + go greInfo.greRead(chEP) + + tcperr = rawEp.Connect(fraddr) + if tcperr != nil { + log.Fatal(tcperr) + } +} |