Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page:
include/odp/api/spec/packet.h
line 129
@@ -1140,6 +1179,82 @@ int odp_packet_move_data(odp_packet_t pkt, uint32_t
dst_offset,
*/
/**
+ * Packet parse parameters
+ */
+typedef struct odp_packet_parse_param_t {
+ /** Protocol header at parse starting point. Valid values for this
+ * field are: ODP_PROTO_ETH, ODP_PROTO_IPV4, ODP_PROTO_IPV6. */
+ odp_proto_t proto;
+
+ /** Continue parsing until this layer. Must be the same or higher
+ * layer than the layer of 'proto'. */
+ odp_proto_layer_t layer;
+
+ /** Flags to control payload data checks up to the selected parse
+ * layer. Checksum checking status can be queried for each packet with
+ * odp_packet_l3_chksum_status() and odp_packet_l4_chksum_status().
+ */
+ union {
+ struct {
+ /** Check IPv4 header checksum */
+ uint32_t ipv4_chksum : 1;
+
+ /** Check UDP checksum */
+ uint32_t udp_chksum : 1;
+
+ /** Check TCP checksum */
+ uint32_t tcp_chksum : 1;
+
+ } check;
+
+ /** All check bits. This can be used to set/clear all flags. */
+ uint32_t all_check;
+ };
+
+} odp_packet_parse_param_t;
+
+/**
+ * Parse packet
+ *
+ * Parse protocol headers in packet data. Parsing starts at 'offset', which
+ * is the first header byte of protocol 'param.proto'. Parameter 'param.layer'
+ * defines the last layer application is interested about.
+ * Use ODP_PROTO_LAYER_ALL for all layers. The operation sets or resets packet
+ * metadata for all layers from the layer of 'param.proto' to the application
+ * defined last layer. Metadata of other layers have undefined values.
+ * When operation fails, metadata of all protocol layers have undefined values.
+ *
+ * @param pkt Packet handle
+ * @param offset Byte offset into the packet
+ * @param param Parse parameters. Proto and layer fields must be set. Clear
+ * all check bits that are not used.
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+int odp_packet_parse(odp_packet_t pkt, uint32_t offset,
+ const odp_packet_parse_param_t *param);
+
+/**
+ * Parse multiple packets
+ *
+ * Otherwise like odp_packet_parse(), but parses multiple packets. Packets may
+ * have unique offsets, but must start with the same protocol. Also, packets
are
+ * parsed up to the same protocol layer.
+ *
+ * @param pkt Packet handle array
+ * @param offset Byte offsets into the packets
+ * @param num Number of packets and offsets
+ * @param param Parse parameters. Proto and layer fields must be set. Clear
+ * all check bits that are not used.
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+int odp_packet_parse_multi(const odp_packet_t pkt[], const uint32_t offset[],
+ int num, const odp_packet_parse_param_t *param);
+
Comment:
Parsing can fail because the packet is malformed in some way. So parsing is
also an important integrity check.
> bogdanPricope wrote
> Then: "When operation fails, metadata of all protocol layers remains
> unchanged." ?
>> bogdanPricope wrote
>> OK
>>> bogdanPricope wrote
>>> Processing of UDP/TCP (in OFP and BSD like) depends on IPv4/IPv6: there are
>>> different input functions for UDP/TCP processing for IPv4 and IPv6
>>> (https://github.com/OpenFastPath/ofp/blob/master/src/ofp_in_proto.c,
>>> https://github.com/OpenFastPath/ofp/blob/master/src/ofp_in6_proto.c)
>>>> Petri Savolainen(psavol) wrote:
>>>> Then I don't add it now. We can add param init also later if param struct
>>>> is extended with other things than check flags. Todays spec defines
>>>> already that all flags should be set to zero.
>>>>
>>>> @param param Parse parameters. Proto and layer fields must be set.
>>>> Clear
>>>> all check bits that are not used.
>>>>> Petri Savolainen(psavol) wrote:
>>>>> Fail means an operation error (bad param, internal error), not e.g. error
>>>>> in packet header formats.
>>>>>> Petri Savolainen(psavol) wrote:
>>>>>> Application calls parse because metadata is not valid to begin with.
>>>>>> There would not be much benefit for application to require that
>>>>>> implementation saves old metadata values before the operation and then
>>>>>> restores those after if e.g. an internal error occurred. Implementation
>>>>>> performance would be hurt by making a copy of the old metadata.
>>>>>>
>>>>>> Since it's just (L2/L3/L4) metadata (not data) that may have changed,
>>>>>> application can continue processing the packet data also after a failed
>>>>>> parse.
>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>> @psavol ok, agreed
>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>> This function is different from e.g. enqueue multi, where the
>>>>>>>> destination queue may be close to full and that's why only part of
>>>>>>>> events were enqueued. Here operation fails due to bad params or
>>>>>>>> internal error.
>>>>>>>>
>>>>>>>> Anyway, I'll change it to return num processed. It's more flexible.
>>>>>>>>> bogdanPricope wrote
>>>>>>>>> What about: "When operation fails, metadata of checked layers
>>>>>>>>> indicates the error condition."?
>>>>>>>>>> bogdanPricope wrote
>>>>>>>>>> What about: "Metadata of other layers remains unmodified."?
>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>> Layer is not enough information for the parser. It needs to know
>>>>>>>>>>> the first protocol (e.g. MPLS vs IP) to be able to start the
>>>>>>>>>>> parsing.
>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>> @psavol `_param_init` seems like an overkill in this case. From my
>>>>>>>>>>>> point of view, `param_init` are good for object creation params
>>>>>>>>>>>> (where we might not know platform-optimized defaults) but are an
>>>>>>>>>>>> overkill for operation functions (we do not have `param_init` for
>>>>>>>>>>>> ipsec, crypto, etc operational params).
>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>> No, other APIs order checksum checking the same way: per
>>>>>>>>>>>>> protocol. Application may be e.g. terminating only UDP and
>>>>>>>>>>>>> forwarding all others - so it would be waste to check e.g. TCP
>>>>>>>>>>>>> checksum.
>>>>>>>>>>>>>
>>>>>>>>>>>>> typedef union odp_pktin_config_opt_t {
>>>>>>>>>>>>> /** Option flags */
>>>>>>>>>>>>> struct {
>>>>>>>>>>>>> /** Timestamp all packets on packet input */
>>>>>>>>>>>>> uint64_t ts_all : 1;
>>>>>>>>>>>>>
>>>>>>>>>>>>> /** Timestamp (at least) IEEE1588 / PTP packets
>>>>>>>>>>>>> * on packet input */
>>>>>>>>>>>>> uint64_t ts_ptp : 1;
>>>>>>>>>>>>>
>>>>>>>>>>>>> /** Check IPv4 header checksum on packet input */
>>>>>>>>>>>>> uint64_t ipv4_chksum : 1;
>>>>>>>>>>>>>
>>>>>>>>>>>>> /** Check UDP checksum on packet input */
>>>>>>>>>>>>> uint64_t udp_chksum : 1;
>>>>>>>>>>>>>
>>>>>>>>>>>>> /** Check TCP checksum on packet input */
>>>>>>>>>>>>> uint64_t tcp_chksum : 1;
>>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>>> Param init on fast path is a bit overkill. However, application
>>>>>>>>>>>>>> could call it once and store the result. So, it could avoid
>>>>>>>>>>>>>> extra function call for every packet. So, I'll add it.
>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>> `return i;` if we adopt the RC == number of successful packets
>>>>>>>>>>>>>>> parsed convention.
>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>> For consistency with other `odp_xxx_multi()` APIs, the RC
>>>>>>>>>>>>>>>> should indicate the number of input packets that were
>>>>>>>>>>>>>>>> successfully processed.
>>>>>>>>>>>>>>>>> muvarov wrote
>>>>>>>>>>>>>>>>> it looks like 2 enums are not needed here. odp_proto_layet_t
>>>>>>>>>>>>>>>>> layer_start; and odp_proto_layet_t layer_end; and one enum
>>>>>>>>>>>>>>>>> for layers.
>>>>>>>>>>>>>>>>>> muvarov wrote
>>>>>>>>>>>>>>>>>> maybe return number of correctly parsed packets? And say
>>>>>>>>>>>>>>>>>> that parsing always starts from be beginning of array.
>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>>>>> +1 since other checksum APIs refer to L3 and L4 rather than
>>>>>>>>>>>>>>>>>>> specific protocols.
>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>> What about just `l3_chksum`, and `l4_chksum`?
>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>>>>>>> Now that we have a `param` struct we should have an
>>>>>>>>>>>>>>>>>>>>> `odp_packet_parse_param_init()` API as well for
>>>>>>>>>>>>>>>>>>>>> completeness.
>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>> @Bill-Fischofer-Linaro Because it is a parsing error, if
>>>>>>>>>>>>>>>>>>>>>> lower layer provides us IP version that does not
>>>>>>>>>>>>>>>>>>>>>> correspond to the in-packet version. We should detect
>>>>>>>>>>>>>>>>>>>>>> that, rather than silently parsing this header.
>>>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>>>>>>>>> I'm not sure why an API named `odp_packet_parse()`
>>>>>>>>>>>>>>>>>>>>>>> needs help here. It's purpose, after all, is to parse
>>>>>>>>>>>>>>>>>>>>>>> packets and determining IPv4 vs IPv6 is part of that
>>>>>>>>>>>>>>>>>>>>>>> activity. Moreover, the only way an application can
>>>>>>>>>>>>>>>>>>>>>>> inspect the IP header is to access it via other ODP API
>>>>>>>>>>>>>>>>>>>>>>> calls, so I don't see how asking the application to do
>>>>>>>>>>>>>>>>>>>>>>> this is any better than having the `odp_packet_parse()`
>>>>>>>>>>>>>>>>>>>>>>> implementation do this itself. What's the purpose of
>>>>>>>>>>>>>>>>>>>>>>> having a parse API in that case since clearly the
>>>>>>>>>>>>>>>>>>>>>>> application could parse the entire packet "by hand" as
>>>>>>>>>>>>>>>>>>>>>>> well.
>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>> Failure needs to be defined in a more precise way (and
>>>>>>>>>>>>>>>>>>>>>>>> maybe for a single packet case). I assume that it
>>>>>>>>>>>>>>>>>>>>>>>> means internal ODP error, rather than just packet with
>>>>>>>>>>>>>>>>>>>>>>>> wrong headers. What happens in multi-packet case if
>>>>>>>>>>>>>>>>>>>>>>>> failure occurs in the middle of parsing?
>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>> @psavol Also for multi-packet parsing, we can change
>>>>>>>>>>>>>>>>>>>>>>>>> `proto` to be an array, allowing applications to
>>>>>>>>>>>>>>>>>>>>>>>>> easily intermix IPv4 and IPv6 packets.
>>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>> @psavol yes. I just wanted to focus on cases, when
>>>>>>>>>>>>>>>>>>>>>>>>>> passing packet with wrong protocol is an error. E.g.
>>>>>>>>>>>>>>>>>>>>>>>>>> IPv6 packet inside IPsec packet with NH = 4. So it
>>>>>>>>>>>>>>>>>>>>>>>>>> is not a question of selecting proper L3 parser, but
>>>>>>>>>>>>>>>>>>>>>>>>>> rather a question of nailing down error/malicious
>>>>>>>>>>>>>>>>>>>>>>>>>> packets.
>>>>>>>>>>>>>>>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>> It's there to enable application to call parsing in
>>>>>>>>>>>>>>>>>>>>>>>>>>> parts - e.g. first up to IP and then continue from
>>>>>>>>>>>>>>>>>>>>>>>>>>> L4. But since IP and transport protocols are tied
>>>>>>>>>>>>>>>>>>>>>>>>>>> together with pseudo headers, it's cleaner to
>>>>>>>>>>>>>>>>>>>>>>>>>>> remove L4 as a starting point.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> First bits of an IP header marks the version. So,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> it would be trivial for both app and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> implementation to read the version from the data.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Common IP define is easier for application when a
>>>>>>>>>>>>>>>>>>>>>>>>>>>> burst of packets may contain both v4 and v6 mixed.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Application does not need to sort packets into
>>>>>>>>>>>>>>>>>>>>>>>>>>>> two arrays (one for v4 and other for v6) but just
>>>>>>>>>>>>>>>>>>>>>>>>>>>> pass the entire array for parsing.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> There are three ways to define the enumeration:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> IP, IPv4+IPv6, IP+IPv4+IPv6. I'm OK with any of
>>>>>>>>>>>>>>>>>>>>>>>>>>>> those. IPv4+IPv6 would be a bit more robust since
>>>>>>>>>>>>>>>>>>>>>>>>>>>> version information comes from two sources.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I felt easier to reparse both L3 and L4 headers
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> in IPsec case, especially since transport mode
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ESP can en/decrypt some of L3 headers in IPv6
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> case.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @Bill-Fischofer-Linaro In IPsec case Next Header
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> field will contain 4 for IPv4 and 41 for IPv6.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> That might be overly complicated since until a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> decrypted tunnel mode IPsec packet is parsed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> you don't know whether it's IPv4 or IPv6. It's
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> parsing that makes that determination.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @lumag IPsec operating in transport mode is,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'd imagine, the main use case here.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> What is the usecase for parsing a packet
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> starting from L4 header? Also there are
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> several (lots) of other L4 protocols. Do we
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> want to support them all here?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Maybe it would be better to split this into
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> separate IPv4 and IPv6 packets. It would be
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> an error to pass IPv6 packet with ethtype
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (or IP tunnel type) being set to IPv4.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> A vector of packets is CPU vector
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> instructions friendly.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Petri Savolainen(psavol) wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> The use case is mentioned in log message:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> parse after decrypt/IP reassembly.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Application has recreated an inner packet
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and needs to parse it before continue.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This is inherently SW parse which may be
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> accelerated with CPU vector instructions,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> etc.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> What's the use case for a multi() form of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> this API? Might VPP use it? Perhaps
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Sachin can comment?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bill Fischofer(Bill-Fischofer-Linaro)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> We had considered an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> `odp_packet_parse()` function some time
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> back but it was rejected as something
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> that would not fit well with hardware
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> parsers. What's changed?
https://github.com/Linaro/odp/pull/273#discussion_r149954064
updated_at 2017-11-09 12:59:36