code: func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
  	for i := 0; i < 2; i++ {
  		_, t, _, v := parseNfAttrTLV(reader)
  		switch t {
  		case nl.CTA_IP_V4_SRC, nl.CTA_IP_V6_SRC:
  			tpl.SrcIP = v
  		case nl.CTA_IP_V4_DST, nl.CTA_IP_V6_DST:
  			tpl.DstIP = v
  		}
  	}
  	// Skip the next 4 bytes  nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO
  	reader.Seek(4, seekCurrent)
  	_, t, _, v := parseNfAttrTLV(reader)
  	if t == nl.CTA_PROTO_NUM {
  		tpl.Protocol = uint8(v[0])
  	}
  	// Skip some padding 3 bytes
  	reader.Seek(3, seekCurrent)
  	for i := 0; i < 2; i++ {
  		_, t, _ := parseNfAttrTL(reader)
  		switch t {
  		case nl.CTA_PROTO_SRC_PORT:
  			parseBERaw16(reader, &tpl.SrcPort)
  		case nl.CTA_PROTO_DST_PORT:
  			parseBERaw16(reader, &tpl.DstPort)
  		}
  		// Skip some padding 2 byte
  		reader.Seek(2, seekCurrent)
  	}
  	return tpl.Protocol
  }
docs: // This method parse the ip tuple structure
  // The message structure is the following:
  // <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC], 16 bytes for the IP>
  // <len, [CTA_IP_V4_DST|CTA_IP_V6_DST], 16 bytes for the IP>
  // <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding>
  // <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding>
  // <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding>