| // Copyright 2016 The Netstack Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package stack |
| |
| import ( |
| "sync" |
| "time" |
| |
| "github.com/google/netstack/tcpip" |
| "github.com/google/netstack/tcpip/buffer" |
| "github.com/google/netstack/waiter" |
| ) |
| |
| // NetworkEndpointID is the identifier of a network layer protocol endpoint. |
| // Currently the local address is sufficient because all supported protocols |
| // (i.e., IPv4 and IPv6) have different sizes for their addresses. |
| type NetworkEndpointID struct { |
| LocalAddress tcpip.Address |
| } |
| |
| // TransportEndpointID is the identifier of a transport layer protocol endpoint. |
| type TransportEndpointID struct { |
| // LocalPort is the local port associated with the endpoint. |
| LocalPort uint16 |
| |
| // LocalAddress is the local [network layer] address associated with |
| // the endpoint. |
| LocalAddress tcpip.Address |
| |
| // RemotePort is the remote port associated with the endpoint. |
| RemotePort uint16 |
| |
| // RemoteAddress it the remote [network layer] address associated with |
| // the endpoint. |
| RemoteAddress tcpip.Address |
| } |
| |
| // TransportEndpoint is the interface that needs to be implemented by transport |
| // protocol (e.g., tcp, udp) endpoints that can handle packets. |
| type TransportEndpoint interface { |
| // HandlePacket is called by the stack when new packets arrive to |
| // this transport endpoint. |
| HandlePacket(r *Route, id TransportEndpointID, vv *buffer.VectorisedView) |
| } |
| |
| // TransportProtocol is the interface that needs to be implemented by transport |
| // protocols (e.g., tcp, udp) that want to be part of the networking stack. |
| type TransportProtocol interface { |
| // Number returns the transport protocol number. |
| Number() tcpip.TransportProtocolNumber |
| |
| // NewEndpoint creates a new endpoint of the transport protocol. |
| NewEndpoint(stack *Stack, netProto tcpip.NetworkProtocolNumber, waitQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) |
| |
| // MinimumPacketSize returns the minimum valid packet size of this |
| // transport protocol. The stack automatically drops any packets smaller |
| // than this targeted at this protocol. |
| MinimumPacketSize() int |
| |
| // ParsePorts returns the source and destination ports stored in a |
| // packet of this protocol. |
| ParsePorts(v buffer.View) (src, dst uint16, err *tcpip.Error) |
| |
| // HandleUnknownDestinationPacket handles packets targeted at this |
| // protocol but that don't match any existing endpoint. For example, |
| // it is targeted at a port that have no listeners. |
| // |
| // The return value indicates whether the packet was well-formed (for |
| // stats purposes only). |
| HandleUnknownDestinationPacket(r *Route, id TransportEndpointID, vv *buffer.VectorisedView) bool |
| |
| // SetOption allows enabling/disabling protocol specific features. |
| // SetOption returns an error if the option is not supported or the |
| // provided option value is invalid. |
| SetOption(option interface{}) *tcpip.Error |
| } |
| |
| // TransportDispatcher contains the methods used by the network stack to deliver |
| // packets to the appropriate transport endpoint after it has been handled by |
| // the network layer. |
| type TransportDispatcher interface { |
| // DeliverTransportPacket delivers the packets to the appropriate |
| // transport protocol endpoint. |
| DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolNumber, vv *buffer.VectorisedView) |
| } |
| |
| // NetworkEndpoint is the interface that needs to be implemented by endpoints |
| // of network layer protocols (e.g., ipv4, ipv6). |
| type NetworkEndpoint interface { |
| // Default TTL is the default time-to-live value (or hop limit, in ipv6) |
| // for this endpoint. |
| DefaultTTL() uint8 |
| |
| // MTU is the maximum transmission unit for this endpoint. This is |
| // generally calculated as the MTU of the underlying data link endpoint |
| // minus the network endpoint max header length. |
| MTU() uint32 |
| |
| // MaxHeaderLength returns the maximum size the network (and lower |
| // level layers combined) headers can have. Higher levels use this |
| // information to reserve space in the front of the packets they're |
| // building. |
| MaxHeaderLength() uint16 |
| |
| // WritePacket writes a packet to the given destination address and |
| // protocol. |
| WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber, ttl uint8) *tcpip.Error |
| |
| // ID returns the network protocol endpoint ID. |
| ID() *NetworkEndpointID |
| |
| // NICID returns the id of the NIC this endpoint belongs to. |
| NICID() tcpip.NICID |
| |
| // HandlePacket is called by the link layer when new packets arrive to |
| // this network endpoint. |
| HandlePacket(r *Route, vv *buffer.VectorisedView) |
| |
| // Close is called when the endpoint is reomved from a stack. |
| Close() |
| } |
| |
| // NetworkProtocol is the interface that needs to be implemented by network |
| // protocols (e.g., ipv4, ipv6) that want to be part of the networking stack. |
| type NetworkProtocol interface { |
| // Number returns the network protocol number. |
| Number() tcpip.NetworkProtocolNumber |
| |
| // MinimumPacketSize returns the minimum valid packet size of this |
| // network protocol. The stack automatically drops any packets smaller |
| // than this targeted at this protocol. |
| MinimumPacketSize() int |
| |
| // ParsePorts returns the source and destination addresses stored in a |
| // packet of this protocol. |
| ParseAddresses(v buffer.View) (src, dst tcpip.Address) |
| |
| // NewEndpoint creates a new endpoint of this protocol. |
| NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint) (NetworkEndpoint, *tcpip.Error) |
| |
| // SetOption allows enabling/disabling protocol specific features. |
| // SetOption returns an error if the option is not supported or the |
| // provided option value is invalid. |
| SetOption(option interface{}) *tcpip.Error |
| } |
| |
| // NetworkDispatcher contains the methods used by the network stack to deliver |
| // packets to the appropriate network endpoint after it has been handled by |
| // the data link layer. |
| type NetworkDispatcher interface { |
| // DeliverNetworkPacket finds the appropriate network protocol |
| // endpoint and hands the packet over for further processing. |
| DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) |
| } |
| |
| // LinkEndpoint is the interface implemented by data link layer protocols (e.g., |
| // ethernet, loopback, raw) and used by network layer protocols to send packets |
| // out through the implementer's data link endpoint. |
| type LinkEndpoint interface { |
| // MTU is the maximum transmission unit for this endpoint. This is |
| // usually dictated by the backing physical network; when such a |
| // physical network doesn't exist, the limit is generally 64k, which |
| // includes the maximum size of an IP packet. |
| MTU() uint32 |
| |
| // MaxHeaderLength returns the maximum size the data link (and |
| // lower level layers combined) headers can have. Higher levels use this |
| // information to reserve space in the front of the packets they're |
| // building. |
| MaxHeaderLength() uint16 |
| |
| // LinkAddress returns the link address (typically a MAC) of the |
| // link endpoint. |
| LinkAddress() tcpip.LinkAddress |
| |
| // WritePacket writes a packet with the given protocol through the given |
| // route. |
| WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error |
| |
| // Attach attaches the data link layer endpoint to the network-layer |
| // dispatcher of the stack. |
| Attach(dispatcher NetworkDispatcher) |
| } |
| |
| // A LinkAddressResolver is an extension to a NetworkProtocol that |
| // can resolve link addresses. |
| type LinkAddressResolver interface { |
| // LinkAddressRequest sends a request for the LinkAddress of addr. |
| // The request is sent on linkEP with localAddr as the source. |
| // |
| // A valid response will cause the discovery protocol's network |
| // endpoint to call AddLinkAddress. |
| LinkAddressRequest(addr, localAddr tcpip.Address, linkEP LinkEndpoint) *tcpip.Error |
| |
| // LinkAddressProtocol returns the network protocol of the |
| // addresses this this resolver can resolve. |
| LinkAddressProtocol() tcpip.NetworkProtocolNumber |
| } |
| |
| // A LinkAddressCache caches link addresses. |
| type LinkAddressCache interface { |
| // CheckLocalAddress determines if the given local address exists, and if it |
| // does, returns the id of the NIC it's bound to. Returns 0 if the address |
| // does not exist. |
| CheckLocalAddress(nicid tcpip.NICID, addr tcpip.Address) tcpip.NICID |
| |
| // AddLinkAddress adds a link address to the cache. |
| AddLinkAddress(nicid tcpip.NICID, addr tcpip.Address, linkAddr tcpip.LinkAddress) |
| |
| GetLinkAddress(nicid tcpip.NICID, addr tcpip.Address, timeout time.Duration) tcpip.LinkAddress |
| } |
| |
| // TransportProtocolFactory functions are used by the stack to instantiate |
| // transport protocols. |
| type TransportProtocolFactory func() TransportProtocol |
| |
| // NetworkProtocolFactory provides methods to be used by the stack to |
| // instantiate network protocols. |
| type NetworkProtocolFactory func() NetworkProtocol |
| |
| var ( |
| transportProtocols = make(map[string]TransportProtocolFactory) |
| networkProtocols = make(map[string]NetworkProtocolFactory) |
| |
| linkEPMu sync.RWMutex |
| nextLinkEndpointID tcpip.LinkEndpointID = 1 |
| linkEndpoints = make(map[tcpip.LinkEndpointID]LinkEndpoint) |
| ) |
| |
| // RegisterTransportProtocolFactory registers a new transport protocol factory |
| // with the stack so that it becomes available to users of the stack. This |
| // function is intended to be called by init() functions of the protocols. |
| func RegisterTransportProtocolFactory(name string, p TransportProtocolFactory) { |
| transportProtocols[name] = p |
| } |
| |
| // RegisterNetworkProtocolFactory registers a new network protocol factory with |
| // the stack so that it becomes available to users of the stack. This function |
| // is intended to be called by init() functions of the protocols. |
| func RegisterNetworkProtocolFactory(name string, p NetworkProtocolFactory) { |
| networkProtocols[name] = p |
| } |
| |
| // RegisterLinkEndpoint register a link-layer protocol endpoint and returns an |
| // ID that can be used to refer to it. |
| func RegisterLinkEndpoint(linkEP LinkEndpoint) tcpip.LinkEndpointID { |
| linkEPMu.Lock() |
| defer linkEPMu.Unlock() |
| |
| v := nextLinkEndpointID |
| nextLinkEndpointID++ |
| |
| linkEndpoints[v] = linkEP |
| |
| return v |
| } |
| |
| // FindLinkEndpoint finds the link endpoint associated with the given ID. |
| func FindLinkEndpoint(id tcpip.LinkEndpointID) LinkEndpoint { |
| linkEPMu.RLock() |
| defer linkEPMu.RUnlock() |
| |
| return linkEndpoints[id] |
| } |