MCPcopy Create free account
hub / github.com/encodeous/nylon / udpGRO

Function udpGRO

polyamide/tun/offload_linux.go:786–858  ·  view source on GitHub ↗

udpGRO evaluates the UDP packet at pktI in bufs for coalescing with existing packets tracked in table. It returns a groResultNoop when no action was taken, groResultTableInsert when the evaluated packet was inserted into table, and groResultCoalesced when the evaluated packet was coalesced with anot

(bufs [][]byte, offset int, pktI int, table *udpGROTable, isV6 bool)

Source from the content-addressed store, hash-verified

784// inserted into table, and groResultCoalesced when the evaluated packet was
785// coalesced with another packet in table.
786func udpGRO(bufs [][]byte, offset int, pktI int, table *udpGROTable, isV6 bool) groResult {
787 pkt := bufs[pktI][offset:]
788 if len(pkt) > maxUint16 {
789 // A valid IPv4 or IPv6 packet will never exceed this.
790 return groResultNoop
791 }
792 iphLen := int((pkt[0] & 0x0F) * 4)
793 if isV6 {
794 iphLen = 40
795 ipv6HPayloadLen := int(binary.BigEndian.Uint16(pkt[4:]))
796 if ipv6HPayloadLen != len(pkt)-iphLen {
797 return groResultNoop
798 }
799 } else {
800 totalLen := int(binary.BigEndian.Uint16(pkt[2:]))
801 if totalLen != len(pkt) {
802 return groResultNoop
803 }
804 }
805 if len(pkt) < iphLen {
806 return groResultNoop
807 }
808 if len(pkt) < iphLen+udphLen {
809 return groResultNoop
810 }
811 if !isV6 {
812 if pkt[6]&ipv4FlagMoreFragments != 0 || pkt[6]<<3 != 0 || pkt[7] != 0 {
813 // no GRO support for fragmented segments for now
814 return groResultNoop
815 }
816 }
817 gsoSize := uint16(len(pkt) - udphLen - iphLen)
818 // not a candidate if payload len is 0
819 if gsoSize < 1 {
820 return groResultNoop
821 }
822 srcAddrOffset := ipv4SrcAddrOffset
823 addrLen := 4
824 if isV6 {
825 srcAddrOffset = ipv6SrcAddrOffset
826 addrLen = 16
827 }
828 items, existing := table.lookupOrInsert(pkt, srcAddrOffset, srcAddrOffset+addrLen, iphLen, pktI)
829 if !existing {
830 return groResultTableInsert
831 }
832 // With UDP we only check the last item, otherwise we could reorder packets
833 // for a given flow. We must also always insert a new item, or successfully
834 // coalesce with an existing item, for the same reason.
835 item := items[len(items)-1]
836 can := udpPacketsCanCoalesce(pkt, uint8(iphLen), gsoSize, item, bufs, offset)
837 var pktCSumKnownInvalid bool
838 if can == coalesceAppend {
839 result := coalesceUDPPackets(pkt, &item, bufs, offset, isV6)
840 switch result {
841 case coalesceSuccess:
842 table.updateAt(item, len(items)-1)
843 return groResultCoalesced

Callers 1

handleGROFunction · 0.85

Calls 5

udpPacketsCanCoalesceFunction · 0.85
coalesceUDPPacketsFunction · 0.85
lookupOrInsertMethod · 0.45
updateAtMethod · 0.45
insertMethod · 0.45

Tested by

no test coverage detected