new file mode 100644
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_DATAPATH_LINUX_COMPAT_INCLUDE_LINUX_OPENVSWITCH_H_H
+#define OVS_DATAPATH_LINUX_COMPAT_INCLUDE_LINUX_OPENVSWITCH_H_H 1
+
+/* -- Used in datapath/linux/compat/include/linux/openvswitch.h -- */
+#define OVS_KEY_ATTRS \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ OVS_KEY_ATTR__${header_name.upper()}, \
+//:: #endfor
+ OVS_KEY_ATTR_VALID, \
+ \
+
+/* -- Used in datapath/linux/compat/include/linux/openvswitch.h -- */
+#define OVS_KEY_STRUCTS \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ struct ovs_key__${header_name} { \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ uint8_t ${field_name}; \
+//:: elif bit_width == 16:
+ ovs_be16 ${field_name}; \
+//:: elif bit_width == 32:
+ ovs_be32 ${field_name}; \
+//:: elif bit_width == 64:
+ ovs_be64 ${field_name}; \
+//:: else:
+ struct ${field_name}_t ${field_name}; \
+//:: #endif
+//:: #endfor
+ }; \
+ \
+//:: #endfor
+ struct ovs_key_valid { \
+//:: for header_name in ordered_header_instances_regular:
+ uint8_t _${header_name}_valid; \
+//:: #endfor
+ }; \
+ \
+
+#endif /* OVS_DATAPATH_LINUX_COMPAT_INCLUDE_LINUX_OPENVSWITCH_H_H */
new file mode 100644
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_INCLUDE_OPENVSWITCH_FLOW_H_H
+#define OVS_INCLUDE_OPENVSWITCH_FLOW_H_H 1
+
+/* -- Used in include/openvswitch/flow.h -- */
+#define OVS_FIELDS \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ struct _${header_name}_padded_header _${header_name}; \
+//:: #endfor
+ struct valid_padded_header valid; \
+ \
+
+#endif /* OVS_INCLUDE_OPENVSWITCH_FLOW_H_H */
new file mode 100644
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_INCLUDE_OPENVSWITCH_META_FLOW_H_H
+#define OVS_INCLUDE_OPENVSWITCH_META_FLOW_H_H 1
+
+/* -- Included in include/openvswitch/meta-flow.h -- */
+
+/* NOTE:
+ * 1. Make sure to add preceding tabs in the following fields, otherwise, will result in errors.
+ * 2. For now prerequisites are not handled.
+ * 3. For now all fields are maskable.
+ */
+
+//:: base_oxm_offset = 45 # NOTE: for now we use 45 as the base line offset. If new fixed fields are added in OVS
+//:: # this number will have to be updated accordingly.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ /* "${field_name}".
+ *
+ * ${field_name} field.
+ *
+ * Type: be${bit_width}.
+ * Formatting: hexadecimal.
+ * Maskable: bitwise.
+ * Prerequisites: none.
+ * Access: read/write.
+ * NXM: none.
+ * OXM: OXM_OF_${field_name.upper()}(${base_oxm_offset}) since OF1.5 and v2.3.
+ */
+ MFF_${field_name.upper()},
+//:: base_oxm_offset += 1
+
+//:: #endfor
+//:: #endfor
+//::
+//:: for header_name in ordered_header_instances_regular:
+ /* "${header_name}_valid".
+ *
+ * ${header_name}_valid field.
+ *
+ * Type: be${8}.
+ * Formatting: hexadecimal.
+ * Maskable: bitwise.
+ * Prerequisites: none.
+ * Access: read/write.
+ * NXM: none.
+ * OXM: OXM_OF_${header_name.upper()}_VALID(${base_oxm_offset}) since OF1.5 and v2.3.
+ */
+ MFF_${header_name.upper()}_VALID,
+//:: base_oxm_offset += 1
+
+//:: #endfor
+
+/* Do NOT REMOVE THIS. */
+ // MFF_N_IDS
+
+#endif /* OVS_INCLUDE_OPENVSWITCH_META_FLOW_H_H */
new file mode 100644
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_INCLUDE_OPENVSWITCH_PACKETS_H_H
+#define OVS_INCLUDE_OPENVSWITCH_PACKETS_H_H 1
+
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: pass
+//:: else:
+//:: header_len = sum([bit_width for _, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]])/8
+#define _${header_name.upper()}_HEADER_LEN ${header_len}
+//:: #endif
+//:: #endfor
+#define VALID_HEADER_LEN ${len(ordered_header_instances_regular)}
+
+/* -- Used in include/openvswitch/packets.h -- */
+#define OVS_HDR_STRUCTS \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: run_bit_width = 0
+ OVS_PACKED( \
+ struct _${header_name}_header { \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ uint8_t ${field_name}; \
+//:: elif bit_width == 16:
+ ovs_be16 ${field_name}; \
+//:: elif bit_width == 32:
+ ovs_be32 ${field_name}; \
+//:: elif bit_width == 64:
+ ovs_be64 ${field_name}; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ struct ${field_name}_t ${field_name}; \
+//:: #endif
+//:: run_bit_width += bit_width
+//:: #endfor
+ }); \
+ BUILD_ASSERT_DECL(_${header_name.upper()}_HEADER_LEN == sizeof(struct _${header_name}_header)); \
+ \
+ OVS_PACKED( \
+ struct _${header_name}_padded_header { \
+ struct _${header_name}_header hdr; \
+//:: pad_bits = 64 - (run_bit_width % 64)
+//:: pad_bytes = 0
+//:: if pad_bits < 64:
+//:: pad_bytes = pad_bits/8
+ uint8_t pad[${pad_bytes}]; \
+//:: #endif
+ }); \
+ BUILD_ASSERT_DECL( \
+ _${header_name.upper()}_HEADER_LEN+${pad_bytes} == sizeof(struct _${header_name}_padded_header)); \
+ \
+//:: #endfor
+ OVS_PACKED( \
+ struct valid_header { \
+//:: for header_name in ordered_header_instances_regular:
+ uint8_t _${header_name}_valid; \
+//:: #endfor
+ }); \
+ BUILD_ASSERT_DECL(VALID_HEADER_LEN == sizeof(struct valid_header)); \
+ \
+ OVS_PACKED( \
+ struct valid_padded_header { \
+ struct valid_header hdr; \
+//:: pad_bits = 64 - ((len(ordered_header_instances_regular)*8) % 64)
+//:: pad_bytes = 0
+//:: if pad_bits < 64:
+//:: pad_bytes = pad_bits/8
+ uint8_t pad[${pad_bytes}]; \
+//:: #endif
+ }); \
+ BUILD_ASSERT_DECL( \
+ VALID_HEADER_LEN+${pad_bytes} == sizeof(struct valid_padded_header)); \
+ \
+
+#endif /* OVS_INCLUDE_OPENVSWITCH_PACKETS_H_H */
new file mode 100644
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_INCLUDE_OPENVSWITCH_TYPES_H_H
+#define OVS_INCLUDE_OPENVSWITCH_TYPES_H_H 1
+
+/* -- Used in include/openvswitch/types.h -- */
+#define OVS_FIELD_STRUCTS \
+//:: for field_name, bit_width in ordered_field_instances_non_virtual__name_width:
+//:: if field_name.startswith("standard_metadata") or field_name.startswith("intrinsic_metadata"):
+//:: continue
+//:: #endif
+//:: if not (bit_width == 8 or bit_width == 16 or bit_width == 32 or bit_width == 64):
+ struct ${field_name}_t { \
+ uint8_t data[${bit_width}/8]; \
+ }; \
+//:: #endif
+//:: #endfor
+ \
+
+#endif /* OVS_INCLUDE_OPENVSWITCH_TYPES_H_H */
new file mode 100644
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_DP_PACKET_H_H
+#define OVS_LIB_DP_PACKET_H_H 1
+
+//:: # NOTE: we don't have to specify metadata in the packet struct in the datapath.
+//:: # The parser can set the value of the metadata but only the final results (after
+//:: # constant propagation) are written in the cache. The only thing different from
+//:: # how native OVS treat metadata is that, in P4/OVS case, parser can set metadata
+//:: # to some arbitrary value, whereas in native OVS, the value of the metadata before
+//:: # being processed by the cache and match-action tables is always 0.
+
+/* -- Used in lib/dp-packet.h -- */
+#define OVS_HDR_ATTRS \
+//:: for header_name in ordered_header_instances_regular:
+ uint16_t _${header_name}_ofs; \
+ uint8_t _${header_name}_valid; \
+//:: #endfor
+ \
+
+/* -- Used in lib/dp-packet.h -- */
+#define OVS_HDR_GET_DP_PACKET_OFS \
+//:: for header_name in ordered_header_instances_regular:
+ static inline void * dp_packet_${header_name}(const struct dp_packet *b) { \
+ return b->_${header_name}_ofs != UINT16_MAX \
+ ? (char *) dp_packet_data(b) + b->_${header_name}_ofs \
+ : NULL; \
+ } \
+//:: #endfor
+ \
+
+#endif /* OVS_LIB_DP_PACKET_H_H */
new file mode 100644
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//:: import math
+//::
+//:: def byte_array_to_int(bytes):
+//:: res = 0
+//:: len_ = len(bytes)
+//:: for i in xrange(len_):
+//:: res += bytes[len_-1-i] << (8 * i)
+//:: #endfor
+//:: return res
+//:: #enddef
+
+#ifndef OVS_LIB_FLOW_C_H
+#define OVS_LIB_FLOW_C_H 1
+
+/* -- Used in lib/flow.c -- */
+#define OVS_HDR_RESET_ATTRS \
+//:: for header_name in ordered_header_instances_regular:
+ packet->_${header_name}_ofs = UINT16_MAX; \
+ packet->_${header_name}_valid = 0; \
+//:: #endfor
+ \
+
+/* -- Used in lib/flow.c -- */
+#define OVS_MINIFLOW_EXTRACT_METADATA_DEFS \
+//:: for header_name in ordered_header_instances_metadata:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ struct _${header_name}_padded_header _${header_name} = {{0},{0}}; \
+ bool is__${header_name}_header_touched = false; \
+ \
+//:: #endfor
+ struct valid_padded_header valid = {{0},{0}}; \
+ \
+
+/* -- Used in lib/flow.c -- */
+#define OVS_MINIFLOW_EXTRACT \
+ { \
+ OVS_MINIFLOW__START \
+ } \
+ \
+
+//:: for state, parse_info in parse_states.items():
+#define OVS_MINIFLOW__${state.upper()} \
+//:: # a) Handle call sequence ###
+//:: call_id = 0
+//:: for call in parse_info["call_sequence"]:
+//:: type = call[0]
+//:: if type == "extract":
+//:: header_name = call[1]
+ if (OVS_UNLIKELY(size < sizeof(struct _${header_name}_header))) \
+ { \
+ OVS_MINIFLOW_OUT \
+ } \
+ \
+ packet->_${header_name}_ofs = ((char *) data) - l2; \
+ struct _${header_name}_padded_header *_${header_name} = (struct _${header_name}_padded_header *) data_pull(&data, &size, \
+ sizeof(struct _${header_name}_header)); \
+//:: # TODO: offset increase should be based on header length expression. This needs to be implemented.
+ miniflow_push_bytes__word_aligned_64(mf, _${header_name}, _${header_name}, sizeof(struct _${header_name}_header), \
+ sizeof(struct _${header_name}_padded_header) / sizeof(uint64_t)); \
+ valid.hdr._${header_name}_valid = 1; \
+ \
+//:: elif type == "set":
+//:: destination = call[1]
+//:: metadata_name = field_info[destination]["parent_header"]
+//:: aligned_metadata_name = aligned_field_info[destination]["name"]
+//:: aligned_metadata_mask = aligned_field_info[destination]["mask"]
+//:: aligned_metadata_bit_offset_hdr = aligned_field_info[destination]["bit_offset_hdr"]
+//:: aligned_metadata_bit_width = aligned_field_info[destination]["bit_width"]
+//:: source_type = call[2]
+//:: if source_type == "immediate":
+//:: source_value = hex(byte_array_to_int(call[3]))
+//:: if aligned_metadata_mask:
+//:: if aligned_metadata_bit_width == 8:
+ _${metadata_name}.hdr.${aligned_metadata_name} = ((uint8_t) ${source_value}) << ${aligned_metadata_bit_offset_hdr} \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~${hex(aligned_metadata_mask)}); \
+//:: elif aligned_metadata_bit_width == 16:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htons(((uint16_t) ${source_value}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htons(${hex(aligned_metadata_mask)})); \
+//:: elif aligned_metadata_bit_width == 32:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonl(((uint32_t) ${source_value}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htonl(${hex(aligned_metadata_mask)})); \
+//:: elif aligned_metadata_bit_width == 64:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonll(((uint64_t) ${source_value}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htonll(${hex(aligned_metadata_mask)})); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: else:
+//:: if aligned_metadata_bit_width == 8:
+ _${metadata_name}.hdr.${aligned_metadata_name} = (uint8_t) ${source_value}; \
+//:: elif aligned_metadata_bit_width == 16:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htons((uint16_t) ${source_value}); \
+//:: elif aligned_metadata_bit_width == 32:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonl((uint32_t) ${source_value}); \
+//:: elif aligned_metadata_bit_width == 64:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonll((uint64_t) ${source_value}); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: #endif
+//:: elif source_type == "latest":
+//:: source = call[3]
+//:: header_name = field_info[source]["parent_header"]
+//:: aligned_field_name = aligned_field_info[source]["name"]
+//:: aligned_field_mask = aligned_field_info[source]["mask"]
+//:: aligned_field_bit_offset_hdr = aligned_field_info[source]["bit_offset_hdr"]
+//:: aligned_field_bit_width = aligned_field_info[source]["bit_width"]
+//:: # NOTE: P4 specification assumes that the referenced source header in set_metadata() is already extracted
+//:: # at this point.
+//:: if header_name in ordered_header_instances_regular:
+//:: if aligned_field_mask:
+//:: if aligned_field_bit_width == 8:
+ uint8_t value_${call_id} = (_${header_name}->hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 16:
+ uint16_t value_${call_id} = (ntohs(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 32:
+ uint32_t value_${call_id} = (ntohl(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 64:
+ uint64_t value_${call_id} = (ntohll(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: else:
+//:: if aligned_field_bit_width == 8:
+ uint8_t value_${call_id} = _${header_name}->hdr.${aligned_field_name}; \
+//:: elif aligned_field_bit_width == 16:
+ uint16_t value_${call_id} = ntohs(_${header_name}->hdr.${aligned_field_name}); \
+//:: elif aligned_field_bit_width == 32:
+ uint32_t value_${call_id} = ntohl(_${header_name}->hdr.${aligned_field_name}); \
+//:: elif aligned_field_bit_width == 64:
+ uint64_t value_${call_id} = ntohll(_${header_name}->hdr.${aligned_field_name}); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: #endif
+//:: elif header_name in ordered_header_instances_metadata:
+//:: if aligned_field_mask:
+//:: if aligned_field_bit_width == 8:
+ uint8_t value_${call_id} = (_${metadata_name}.hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 16:
+ uint16_t value_${call_id} = (ntohs(_${metadata_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 32:
+ uint32_t value_${call_id} = (nothl(_${metadata_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: elif aligned_field_bit_width == 64:
+ uint64_t value_${call_id} = (ntohll(_${metadata_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}; \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: else:
+//:: if aligned_field_bit_width == 8:
+ uint8_t value_${call_id} = _${metadata_name}.hdr.${aligned_field_name}; \
+//:: elif aligned_field_bit_width == 16:
+ uint16_t value_${call_id} = ntohs(_${metadata_name}.hdr.${aligned_field_name}); \
+//:: elif aligned_field_bit_width == 32:
+ uint32_t value_${call_id} = ntohl(_${metadata_name}.hdr.${aligned_field_name}); \
+//:: elif aligned_field_bit_width == 64:
+ uint64_t value_${call_id} = ntohll(_${metadata_name}.hdr.${aligned_field_name}); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: #endif
+//:: else:
+//:: assert(False)
+//:: #endif
+//:: if aligned_metadata_mask:
+//:: if aligned_metadata_bit_width == 8:
+ _${metadata_name}.hdr.${aligned_metadata_name} = ((uint8_t) value_${call_id}) << ${aligned_metadata_bit_offset_hdr} \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~${hex(aligned_metadata_mask)}); \
+//:: elif aligned_metadata_bit_width == 16:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htons(((uint16_t) value_${call_id}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htons(${hex(aligned_metadata_mask)})); \
+//:: elif aligned_metadata_bit_width == 32:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonl((uint32_t) value_${call_id}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htonl(${hex(aligned_metadata_mask)})); \
+//:: elif aligned_metadata_bit_width == 64:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonll((uint64_t) value_${call_id}) << ${aligned_metadata_bit_offset_hdr}) \
+ | (_${metadata_name}.hdr.${aligned_metadata_name} & ~htonll(${hex(aligned_metadata_mask)})); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: else:
+//:: if aligned_metadata_bit_width == 8:
+ _${metadata_name}.hdr.${aligned_metadata_name} = (uint8_t) value_${call_id}; \
+//:: elif aligned_metadata_bit_width == 16:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htons((uint16_t) value_${call_id}); \
+//:: elif aligned_metadata_bit_width == 32:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonl((uint32_t) value_${call_id}); \
+//:: elif aligned_metadata_bit_width == 64:
+ _${metadata_name}.hdr.${aligned_metadata_name} = htonll((uint64_t) value_${call_id}); \
+//:: else:
+//:: assert(False) # TODO: handle this case (for arbitrary byte combinations).
+//:: #endif
+//:: #endif
+//:: else:
+//:: assert(False) # TODO: handle this case (e.g., current() etc).
+//:: #endif
+ is__${metadata_name}_header_touched = true; \
+ \
+//:: else:
+//:: assert(False)
+//:: #endif
+//:: call_id += 1
+//:: #endfor
+//:: # b) Handle state transitions ###
+//:: branch_on = parse_info['branch_on']
+//:: branch_to = parse_info['branch_to']
+//:: case_id = 0
+//:: for case in branch_to:
+//:: case_type, case_value, case_mask, case_next_state = case
+//:: if case_type == "value":
+//:: branch_id = 0
+//:: key_id = 0
+//:: for key_type, key_value in branch_on:
+//:: if key_type == "field_ref":
+//:: header_name = field_info[key_value]["parent_header"]
+//:: aligned_field_name = aligned_field_info[key_value]["name"]
+//:: aligned_field_bit_width = aligned_field_info[key_value]["bit_width"]
+//:: aligned_field_mask = aligned_field_info[key_value]["mask"]
+//:: aligned_field_bit_offset_hdr = aligned_field_info[key_value]["bit_offset_hdr"]
+//:: if header_name in ordered_header_instances_regular:
+//:: if aligned_field_bit_width == 8:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((_${header_name}->hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (_${header_name}->hdr.${aligned_field_name} == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 16:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs(_${header_name}->hdr.${aligned_field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 32:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl(_${header_name}->hdr.${aligned_field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((nothll(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohll(_${header_name}->hdr.${field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: #endif
+//:: key_id += 8
+//:: elif aligned_field_bit_width <= 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}->hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = ((temp & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr} == ${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))}); \
+ } \
+//:: else:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}->hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = (temp == ${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))}); \
+ } \
+//:: #endif
+//:: key_id += aligned_field_bit_width/8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: elif header_name in ordered_header_instances_metadata:
+//:: if aligned_field_bit_width == 8:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((_${header_name}.hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (_${header_name}.hdr.${aligned_field_name} == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 16:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs(_${header_name}.hdr.${aligned_field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 32:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl(_${header_name}.hdr.${aligned_field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((nothll(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohll(_${header_name}.hdr.${aligned_field_name}) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: #endif
+//:: key_id += 8
+//:: elif aligned_field_bit_width <= 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}.hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = (temp & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr} == ${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))}); \
+ } \
+//:: else:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}.hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = (temp == ${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))}); \
+ } \
+//:: #endif
+//:: key_id += aligned_field_bit_width/8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: #endif
+//:: elif key_type == "current":
+//:: key_bit_offset, key_bit_width = key_value
+//:: aligned_key_bit_base_offset = int(key_bit_offset/8)*8
+//:: adjusted_key_bit_offset = key_bit_offset - aligned_key_bit_base_offset
+//:: aligned_key_bit_width = int(math.ceil((adjusted_key_bit_offset+key_bit_width)/8.0)*8)
+//:: aligned_key_bit_offset_hdr = aligned_key_bit_width - ((adjusted_key_bit_offset%aligned_key_bit_width) + key_bit_width)
+//:: aligned_key_mask = ((1 << key_bit_width) - 1) << aligned_key_bit_offset_hdr
+//:: aligned_key_mask = 0 if (((1 << aligned_key_bit_width) - 1) == aligned_key_mask) else aligned_key_mask
+ if (OVS_UNLIKELY(size < (${aligned_key_bit_base_offset/8}+${aligned_key_bit_width/8}))) { OVS_MINIFLOW_OUT } \
+//:: if aligned_key_bit_width == 8:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = ((((*(uint8_t *) (((char *) data) + ${aligned_key_bit_base_offset/8})) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = ((*(uint8_t *) (((char *) data) + ${aligned_key_bit_base_offset/8})) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 16:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs((*(ovs_be16 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs((*(ovs_be16 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 32:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl((*(ovs_be32 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl((*(ovs_be32 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == ${hex(byte_array_to_int(case_value[key_id:key_id+4]))}); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 64:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl((*(ovs_be64 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl((*(ovs_be64 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == ${hex(byte_array_to_int(case_value[key_id:key_id+8]))}); \
+//:: #endif
+//:: key_id += 8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: else:
+//:: assert(False)
+//:: #endif
+//:: branch_id += 1
+//:: #endfor
+ if ( \
+//:: branch_id = 0
+//:: for key_type, key_value in branch_on:
+ check_${case_id}_${branch_id} && \
+//:: branch_id += 1
+//:: #endfor
+ true) \
+//:: elif case_type == "value_masked":
+//:: branch_id = 0
+//:: key_id = 0
+//:: for key_type, key_value in branch_on:
+//:: if key_type == "field_ref":
+//:: header_name = field_info[key_value]["parent_header"]
+//:: aligned_field_name = aligned_field_info[key_value]["name"]
+//:: aligned_field_bit_width = aligned_field_info[key_value]["bit_width"]
+//:: aligned_field_mask = aligned_field_info[key_value]["mask"]
+//:: aligned_field_bit_offset_hdr = aligned_field_info[key_value]["bit_offset_hdr"]
+//:: if header_name in ordered_header_instances_regular:
+//:: if aligned_field_bit_width == 8:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((_${header_name}->hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (_${header_name}->hdr.${aligned_field_name} == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 16:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs(_${header_name}->hdr.${aligned_field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 32:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl(_${header_name}->hdr.${aligned_field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((nothll(_${header_name}->hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohll(_${header_name}->hdr.${field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: #endif
+//:: key_id += 8
+//:: elif aligned_field_bit_width <= 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}->hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = ((temp & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr} == (${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+(aligned_field_bit_width/8)]))})); \
+ } \
+//:: else:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}->hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = (temp == (${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+(aligned_field_bit_width/8)]))})); \
+ } \
+//:: #endif
+//:: key_id += aligned_field_bit_width/8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: elif header_name in ordered_header_instances_metadata:
+//:: if aligned_field_bit_width == 8:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((_${header_name}.hdr.${aligned_field_name} & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (_${header_name}.hdr.${aligned_field_name} == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 16:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs(_${header_name}.hdr.${aligned_field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 32:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl(_${header_name}.hdr.${aligned_field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_field_bit_width == 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = (((nothll(_${header_name}.hdr.${aligned_field_name}) & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohll(_${header_name}.hdr.${aligned_field_name}) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: #endif
+//:: key_id += 8
+//:: elif aligned_field_bit_width <= 64:
+//:: if aligned_field_mask:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}.hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = ((temp & ${hex(aligned_field_mask)}) >> ${aligned_field_bit_offset_hdr} == (${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+(aligned_field_bit_width/8)]))})); \
+ } \
+//:: else:
+ bool check_${case_id}_${branch_id} = false; \
+ { \
+ uint64_t temp = 0; \
+//:: for i in range(aligned_field_bit_width/8):
+ temp |= ((const uint8_t *) &_${header_name}.hdr.${aligned_field_name})[${i}]; temp <<= (${aligned_field_bit_width} - (8 * (${i} + 1))); \
+//:: #endfor
+ check_${case_id}_${branch_id} = (temp == (${hex(byte_array_to_int(case_value[key_id:key_id+(aligned_field_bit_width/8)]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+(aligned_field_bit_width/8)]))})); \
+ } \
+//:: #endif
+//:: key_id += aligned_field_bit_width/8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: #endif
+//:: elif key_type == "current":
+//:: key_bit_offset, key_bit_width = key_value
+//:: aligned_key_bit_base_offset = int(key_bit_offset/8)*8
+//:: adjusted_key_bit_offset = key_bit_offset - aligned_key_bit_base_offset
+//:: aligned_key_bit_width = int(math.ceil((adjusted_key_bit_offset+key_bit_width)/8.0)*8)
+//:: aligned_key_bit_offset_hdr = aligned_key_bit_width - ((adjusted_key_bit_offset%aligned_key_bit_width) + key_bit_width)
+//:: aligned_key_mask = ((1 << key_bit_width) - 1) << aligned_key_bit_offset_hdr
+//:: aligned_key_mask = 0 if (((1 << aligned_key_bit_width) - 1) == aligned_key_mask) else aligned_key_mask
+ if (OVS_UNLIKELY(size < (${aligned_key_bit_base_offset/8}+${aligned_key_bit_width/8}))) { OVS_MINIFLOW_OUT } \
+//:: if aligned_key_bit_width == 8:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = ((((*(uint8_t *) (((char *) data) + ${aligned_key_bit_base_offset/8})) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = ((*(uint8_t *) (((char *) data) + ${aligned_key_bit_base_offset/8})) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 16:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohs((*(ovs_be16 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohs((*(ovs_be16 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 32:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl((*(ovs_be32 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl((*(ovs_be32 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == (${hex(byte_array_to_int(case_value[key_id:key_id+4]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+4]))})); \
+//:: #endif
+//:: key_id += 4
+//:: elif aligned_key_bit_width == 64:
+//:: if aligned_key_mask:
+ bool check_${case_id}_${branch_id} = (((ntohl((*(ovs_be64 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) & ${hex(aligned_key_mask)}) >> ${aligned_key_bit_offset_hdr}) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: else:
+ bool check_${case_id}_${branch_id} = (ntohl((*(ovs_be64 *) (((char *) data) + ${aligned_key_bit_base_offset/8}))) == (${hex(byte_array_to_int(case_value[key_id:key_id+8]))} & ${hex(byte_array_to_int(case_mask[key_id:key_id+8]))})); \
+//:: #endif
+//:: key_id += 8
+//:: else:
+//:: assert(False) # TODO: right now only covers up to 64 bits, look into how to extend this range.
+//:: #endif
+//:: else:
+//:: assert(False)
+//:: #endif
+//:: branch_id += 1
+//:: #endfor
+ if ( \
+//:: branch_id = 0
+//:: for key_type, key_value in branch_on:
+ check_${case_id}_${branch_id} && \
+//:: branch_id += 1
+//:: #endfor
+ true) \
+//:: elif case_type == "default":
+//:: pass
+//:: else:
+//:: assert(False)
+//:: #endif
+ { \
+//:: if case_next_state[0] == "parse_state":
+ OVS_MINIFLOW__${case_next_state[1].upper()} \
+//:: elif case_next_state[0] == "table" or case_next_state[0] == "conditional_table":
+ OVS_MINIFLOW_OUT \
+//:: else:
+//:: assert(False)
+//:: #endif
+ } \
+ \
+//:: case_id += 1
+//:: #endfor
+
+//:: #endfor
+#define OVS_MINIFLOW_OUT \
+//:: for header_name in ordered_header_instances_metadata:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ if (OVS_LIKELY(is__${header_name}_header_touched)) \
+ { \
+ miniflow_push_bytes__word_aligned_64(mf, _${header_name}, &_${header_name}, sizeof(struct _${header_name}_header), \
+ sizeof(struct _${header_name}_padded_header) / sizeof(uint64_t)); \
+ } \
+//:: #endfor
+ \
+ miniflow_push_bytes__word_aligned_64(mf, valid, &valid, sizeof(struct valid_header), \
+ sizeof(struct valid_padded_header) / sizeof(uint64_t)); \
+ goto out_; \
+ \
+
+/* -- Used in lib/flow.c -- */
+#define OVS_FLOW_WC_MASK \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ WC_MASK_FIELD(wc, _${header_name}); \
+//:: #endfor
+ \
+
+/* -- Used in lib/flow.c -- */
+#define OVS_FLOW_WC_MAP \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ FLOWMAP_SET(map, _${header_name}); \
+//:: #endfor
+ FLOWMAP_SET(map, valid); \
+ \
+
+#endif /* OVS_LIB_FLOW_C_H */
new file mode 100644
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_MATCH_C_H
+#define OVS_LIB_MATCH_C_H 1
+
+/* -- Used in lib/match.c -- */
+#define OVS_MATCH_FORMAT \
+ \
+
+#define OVS_MATCH_FORMAT_DISABLED \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ format_be8_masked(s, "${field_name}", f->_${header_name}.hdr.${field_name}, \
+ wc->masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 16:
+ format_be16_masked(s, "${field_name}", f->_${header_name}.hdr.${field_name}, \
+ wc->masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 32:
+ format_be32_masked(s, "${field_name}", f->_${header_name}.hdr.${field_name}, \
+ wc->masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 64:
+ format_be64_masked(s, "${field_name}", f->_${header_name}.hdr.${field_name}, \
+ wc->masks._${header_name}.hdr.${field_name}); \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ format_bex_masked(s, "${field_name}", \
+ (const uint8_t *) &f->_${header_name}.hdr.${field_name}, \
+ (const uint8_t *) &wc->masks._${header_name}.hdr.${field_name}, \
+ sizeof f->_${header_name}.hdr.${field_name}); \
+//:: #endif
+//:: #endfor
+ \
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ format_be8_masked(s, "${header_name}_valid", f->valid.hdr._${header_name}_valid, \
+ wc->masks.valid.hdr._${header_name}_valid); \
+//:: #endfor
+ \
+
+#endif /* OVS_LIB_MATCH_C_H */
new file mode 100644
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_META_FLOW_C_H
+#define OVS_LIB_META_FLOW_C_H 1
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_GET_VALUE_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8:
+ value->u8 = flow->_${header_name}.hdr.${field_name}; \
+//:: elif bit_width == 16:
+ value->be16 = flow->_${header_name}.hdr.${field_name}; \
+//:: elif bit_width == 32:
+ value->be32 = flow->_${header_name}.hdr.${field_name}; \
+//:: elif bit_width == 64:
+ value->be64 = flow->_${header_name}.hdr.${field_name}; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ memcpy(value->data, &flow->_${header_name}.hdr.${field_name}, \
+ sizeof flow->_${header_name}.hdr.${field_name}); \
+//:: #endif
+ break; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ value->u8 = flow->valid.hdr._${header_name}_valid; \
+ break; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_IS_VALUE_VALID_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+ return true; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ return true; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_IS_ALL_WILD_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8 or bit_width == 16 or bit_width == 32 or bit_width == 64:
+ return !wc->masks._${header_name}.hdr.${field_name}; \
+//:: else:
+ return is_all_zeros(&wc->masks._${header_name}.hdr.${field_name}, \
+ sizeof wc->masks._${header_name}.hdr.${field_name}); \
+//:: #endif
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ return !wc->masks.valid.hdr._${header_name}_valid; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_SET_FLOW_VALUE_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8:
+ flow->_${header_name}.hdr.${field_name} = value->u8; \
+//:: elif bit_width == 16:
+ flow->_${header_name}.hdr.${field_name} = value->be16; \
+//:: elif bit_width == 32:
+ flow->_${header_name}.hdr.${field_name} = value->be32; \
+//:: elif bit_width == 64:
+ flow->_${header_name}.hdr.${field_name} = value->be64; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ memcpy(&flow->_${header_name}.hdr.${field_name}, value->data, \
+ sizeof flow->_${header_name}.hdr.${field_name}); \
+//:: #endif
+ break; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ flow->valid.hdr._${header_name}_valid = value->u8; \
+ break; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_SET_VLAUE_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8:
+ match->wc.masks._${header_name}.hdr.${field_name} = 0xff; \
+ match->flow._${header_name}.hdr.${field_name} = value->u8; \
+//:: elif bit_width == 16:
+ match->wc.masks._${header_name}.hdr.${field_name} = OVS_BE16_MAX; \
+ match->flow._${header_name}.hdr.${field_name} = value->be16; \
+//:: elif bit_width == 32:
+ match->wc.masks._${header_name}.hdr.${field_name} = OVS_BE32_MAX; \
+ match->flow._${header_name}.hdr.${field_name} = value->be32; \
+//:: elif bit_width == 64:
+ match->wc.masks._${header_name}.hdr.${field_name} = OVS_BE64_MAX; \
+ match->flow._${header_name}.hdr.${field_name} = value->be64; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ memset(&match->wc.masks._${header_name}.hdr.${field_name}, 0xff, \
+ sizeof match->wc.masks._${header_name}.hdr.${field_name}); \
+ memcpy(&match->flow._${header_name}.hdr.${field_name}, value->data, \
+ sizeof match->flow._${header_name}.hdr.${field_name}); \
+//:: #endif
+ break; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ match->wc.masks.valid.hdr._${header_name}_valid = 0xff; \
+ match->flow.valid.hdr._${header_name}_valid = value->u8; \
+ break; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_SET_WILD_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8 or bit_width == 16 or bit_width == 32 or bit_width == 64:
+ match->flow._${header_name}.hdr.${field_name} = 0; \
+ match->wc.masks._${header_name}.hdr.${field_name} = 0; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ memset(&match->flow._${header_name}.hdr.${field_name}, 0, \
+ sizeof match->flow._${header_name}.hdr.${field_name}); \
+ memset(&match->wc.masks._${header_name}.hdr.${field_name}, 0, \
+ sizeof match->wc.masks._${header_name}.hdr.${field_name}); \
+//:: #endif
+ break; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ match->flow.valid.hdr._${header_name}_valid = 0; \
+ match->wc.masks.valid.hdr._${header_name}_valid = 0; \
+ break; \
+//:: #endfor
+ \
+
+/* -- Used in lib/meta-flow.c -- */
+#define OVS_SET_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ case MFF_${field_name.upper()}: \
+//:: if bit_width == 8:
+ match->flow._${header_name}.hdr.${field_name} = value->u8 & mask->u8; \
+ match->wc.masks._${header_name}.hdr.${field_name} = mask->u8; \
+//:: elif bit_width == 16:
+ match->flow._${header_name}.hdr.${field_name} = value->be16 & mask->be16; \
+ match->wc.masks._${header_name}.hdr.${field_name} = mask->be16; \
+//:: elif bit_width == 32:
+ match->flow._${header_name}.hdr.${field_name} = value->be32 & mask->be32; \
+ match->wc.masks._${header_name}.hdr.${field_name} = mask->be32; \
+//:: elif bit_width == 64:
+ match->flow._${header_name}.hdr.${field_name} = value->be64 & mask->be64; \
+ match->wc.masks._${header_name}.hdr.${field_name} = mask->be64; \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ for (size_t i = 0; i < sizeof match->flow._${header_name}.hdr.${field_name}; i++) { \
+ ((uint8_t *) &match->flow._${header_name}.hdr.${field_name})[i] = (value->data)[i] & (mask->data)[i]; \
+ ((uint8_t *) &match->wc.masks._${header_name}.hdr.${field_name})[i] = (mask->data)[i]; \
+ } \
+//:: #endif
+ break; \
+//:: #endfor
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case MFF_${header_name.upper()}_VALID: \
+ match->flow.valid.hdr._${header_name}_valid = value->u8 & mask->u8; \
+ match->wc.masks.valid.hdr._${header_name}_valid = mask->u8; \
+ break; \
+//:: #endfor
+ \
+
+#endif /* OVS_LIB_META_FLOW_C_H */
new file mode 100644
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_NX_MATCH_C_H
+#define OVS_LIB_NX_MATCH_C_H 1
+
+/* -- Used in lib/nx-match.c -- */
+#define OVS_MATCH_PUT_RAW \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ nxm_put_8m(b, MFF_${field_name.upper()}, oxm, \
+ flow->_${header_name}.hdr.${field_name}, \
+ match->wc.masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 16:
+ nxm_put_16m(b, MFF_${field_name.upper()}, oxm, \
+ flow->_${header_name}.hdr.${field_name}, \
+ match->wc.masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 32:
+ nxm_put_32m(b, MFF_${field_name.upper()}, oxm, \
+ flow->_${header_name}.hdr.${field_name}, \
+ match->wc.masks._${header_name}.hdr.${field_name}); \
+//:: elif bit_width == 64:
+ nxm_put_64m(b, MFF_${field_name.upper()}, oxm, \
+ flow->_${header_name}.hdr.${field_name}, \
+ match->wc.masks._${header_name}.hdr.${field_name}); \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ nxm_put(b, MFF_${field_name.upper()}, oxm, \
+ &flow->_${header_name}.hdr.${field_name}, \
+ &match->wc.masks._${header_name}.hdr.${field_name}, \
+ sizeof flow->_${header_name}.hdr.${field_name}); \
+//:: #endif
+//:: #endfor
+ \
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ nxm_put_8m(b, MFF_${header_name.upper()}_VALID, oxm, \
+ flow->valid.hdr._${header_name}_valid, \
+ match->wc.masks.valid.hdr._${header_name}_valid); \
+//:: #endfor
+ \
+
+#endif /* OVS_LIB_NX_MATCH_C_H */
new file mode 100644
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_ODP_EXECUTE_C_H
+#define OVS_LIB_ODP_EXECUTE_C_H 1
+
+/* -- Used in lib/odp-execute.c -- */
+#define OVS_ODP_SET_ACTION_FUNCS \
+//:: for header_name in ordered_header_instances_regular:
+ static void \
+ odp_set__${header_name}(struct dp_packet *packet, const struct ovs_key__${header_name} *key, \
+ const struct ovs_key__${header_name} *mask) \
+ { \
+ struct _${header_name}_header *_${header_name} = dp_packet_${header_name}(packet); \
+ \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ uint8_t ${field_name} = key->${field_name} | (_${header_name}->${field_name} & ~mask->${field_name}); \
+//:: elif bit_width == 16:
+ ovs_be16 ${field_name} = key->${field_name} | (_${header_name}->${field_name} & ~mask->${field_name}); \
+//:: elif bit_width == 32:
+ ovs_be32 ${field_name} = key->${field_name} | (_${header_name}->${field_name} & ~mask->${field_name}); \
+//:: elif bit_width == 64:
+ ovs_be64 ${field_name} = key->${field_name} | (_${header_name}->${field_name} & ~mask->${field_name}); \
+//:: else:
+ struct ${field_name}_t ${field_name}; \
+ for (size_t i = 0; i < sizeof(struct ${field_name}_t); i++) { \
+ ((uint8_t *) &${field_name})[i] = ((const uint8_t *) &key->${field_name})[i] | \
+ (((const uint8_t *) &_${header_name}->${field_name})[i] & \
+ ~((const uint8_t *) &mask->${field_name})[i]); \
+ } \
+//:: #endif
+//:: #endfor
+ \
+ packet_set__${header_name}( \
+//:: for field_name, _ in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ ${field_name}, \
+//:: #endfor
+ packet); \
+ } \
+ \
+//:: #endfor
+ static void \
+ odp_set_valid(struct dp_packet *packet, const struct ovs_key_valid *key, \
+ const struct ovs_key_valid *mask) \
+ { \
+//:: for header_name in ordered_header_instances_regular:
+ uint8_t _${header_name}_valid = key->_${header_name}_valid | (packet->_${header_name}_valid & ~mask->_${header_name}_valid); \
+//:: #endfor
+ \
+ packet_set_valid( \
+//:: for header_name in ordered_header_instances_regular:
+ _${header_name}_valid, \
+//:: #endfor
+ packet); \
+ } \
+ \
+
+/* -- Used in lib/odp-execute.c -- */
+#define OVS_ODP_EXECUTE_SET_ACTION_CASES \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_metadata:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ break; \
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ { \
+ const struct ovs_key__${header_name} *_${header_name}_key = \
+ nl_attr_get_unspec(a, sizeof(struct ovs_key__${header_name})); \
+ packet_set__${header_name}( \
+//:: for field_name, _ in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ _${header_name}_key->${field_name}, \
+//:: #endfor
+ packet); \
+ break; \
+ } \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: \
+ { \
+ const struct ovs_key_valid *valid_key = \
+ nl_attr_get_unspec(a, sizeof(struct ovs_key_valid)); \
+ packet_set_valid( \
+//:: for header_name in ordered_header_instances_regular:
+ valid_key->_${header_name}_valid, \
+//:: #endfor
+ packet); \
+ break; \
+ } \
+ \
+
+/* -- Used in lib/odp-execute.c -- */
+#define OVS_ODP_EXECUTE_MASKED_SET_ACTION_CASES \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_metadata:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ break; \
+//:: #endfor
+//:: for header_name in ordered_header_instances_regular:
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ odp_set__${header_name}(packet, nl_attr_get(a), \
+ get_mask(a, struct ovs_key__${header_name})); \
+ break; \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: \
+ odp_set_valid(packet, nl_attr_get(a), \
+ get_mask(a, struct ovs_key_valid)); \
+ break; \
+ \
+
+#endif /* OVS_LIB_ODP_EXECUTE_C_H */
new file mode 100644
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_ODP_UTIL_C_H
+#define OVS_LIB_ODP_UTIL_C_H 1
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_KEY_ATTRS_TO_STRING_CASES \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: return "${header_name}"; \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: return "valid"; \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_FORMAT_ODP_KEY_ATTR_CASES \
+
+#define OVS_FORMAT_ODP_KEY_ATTR_CASES_DISABLED \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: { \
+ const struct ovs_key__${header_name} *key = nl_attr_get(a); \
+ const struct ovs_key__${header_name} *mask = ma ? nl_attr_get(ma) : NULL; \
+ \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ format_u8x(ds, "${field_name}", key->${field_name}, MASK(mask, ${field_name}), verbose); \
+//:: elif bit_width == 16:
+ format_be16x(ds, "${field_name}", key->${field_name}, MASK(mask, ${field_name}), verbose); \
+//:: elif bit_width == 32:
+ format_be32x(ds, "${field_name}", key->${field_name}, MASK(mask, ${field_name}), verbose); \
+//:: elif bit_width == 64:
+ format_be64x(ds, "${field_name}", key->${field_name}, MASK(mask, ${field_name}), verbose); \
+//:: else:
+ format_bex(ds, "${field_name}", (const uint8_t *) &key->${field_name}, \
+ mask ? (const uint8_t (*)[]) &mask->${field_name} : NULL, \
+ sizeof(struct ${field_name}_t), verbose); \
+//:: #endif
+//:: #endfor
+ ds_chomp(ds, ','); \
+ break; \
+ } \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: { \
+ const struct ovs_key_valid *key = nl_attr_get(a); \
+ const struct ovs_key_valid *mask = ma ? nl_attr_get(ma) : NULL; \
+ \
+//:: for header_name in ordered_header_instances_regular:
+ format_u8x(ds, "${header_name}_valid", key->_${header_name}_valid, MASK(mask, _${header_name}_valid), verbose); \
+//:: #endfor
+ ds_chomp(ds, ','); \
+ break; \
+ } \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_SET_FUNC_DECLS \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ static void \
+ get__${header_name}_key(const struct flow *flow, struct ovs_key__${header_name} *_${header_name}); \
+ static void \
+ put__${header_name}_key(const struct ovs_key__${header_name} *_${header_name}, struct flow *flow); \
+ \
+//:: #endfor
+ static void \
+ get_valid_key(const struct flow *flow, struct ovs_key_valid *valid); \
+ static void \
+ put_valid_key(const struct ovs_key_valid *valid, struct flow *flow); \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_SET_FUNC_DEFS \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ static void \
+ get__${header_name}_key(const struct flow *flow, struct ovs_key__${header_name} *_${header_name}) \
+ { \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ _${header_name}->${field_name} = flow->_${header_name}.hdr.${field_name}; \
+//:: #endfor
+ } \
+ \
+ static void \
+ put__${header_name}_key(const struct ovs_key__${header_name} *_${header_name}, struct flow *flow) \
+ { \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ flow->_${header_name}.hdr.${field_name} = _${header_name}->${field_name}; \
+//:: #endfor
+ } \
+ \
+//:: #endfor
+ static void \
+ get_valid_key(const struct flow *flow, struct ovs_key_valid *valid) \
+ { \
+//:: for header_name in ordered_header_instances_regular:
+ valid->_${header_name}_valid = flow->valid.hdr._${header_name}_valid; \
+//:: #endfor
+ } \
+ \
+ static void \
+ put_valid_key(const struct ovs_key_valid *valid, struct flow *flow) \
+ { \
+//:: for header_name in ordered_header_instances_regular:
+ flow->valid.hdr._${header_name}_valid = valid->_${header_name}_valid; \
+//:: #endfor
+ } \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_COMMIT_ACTION_FUNCS \
+//:: for header_name in ordered_header_instances_regular:
+ static void \
+ commit_set__${header_name}_action(const struct flow *flow, struct flow *base_flow, \
+ struct ofpbuf *odp_actions, \
+ struct flow_wildcards *wc, \
+ bool use_masked) \
+ { \
+ struct ovs_key__${header_name} key, base, mask; \
+ \
+ get__${header_name}_key(flow, &key); \
+ get__${header_name}_key(base_flow, &base); \
+ get__${header_name}_key(&wc->masks, &mask); \
+ \
+ if (commit(OVS_KEY_ATTR__${header_name.upper()}, use_masked, \
+ &key, &base, &mask, sizeof key, odp_actions)) { \
+ put__${header_name}_key(&base, base_flow); \
+ put__${header_name}_key(&mask, &wc->masks); \
+ } \
+ } \
+ \
+//:: #endfor
+ static void \
+ commit_set_valid_action(const struct flow *flow, struct flow *base_flow, \
+ struct ofpbuf *odp_actions, \
+ struct flow_wildcards *wc, \
+ bool use_masked) \
+ { \
+ struct ovs_key_valid key, base, mask; \
+ \
+ get_valid_key(flow, &key); \
+ get_valid_key(base_flow, &base); \
+ get_valid_key(&wc->masks, &mask); \
+ \
+ if (commit(OVS_KEY_ATTR_VALID, use_masked, \
+ &key, &base, &mask, sizeof key, odp_actions)) { \
+ put_valid_key(&base, base_flow); \
+ put_valid_key(&mask, &wc->masks); \
+ } \
+ } \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_COMMIT_ODP_ACTIONS_FUNCS \
+//:: for header_name in ordered_header_instances_regular:
+ commit_set__${header_name}_action(flow, base, odp_actions, wc, use_masked); \
+//:: #endfor
+ commit_set_valid_action(flow, base, odp_actions, wc, use_masked); \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_FLOW_KEY_ATTR_LENS \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ [OVS_KEY_ATTR__${header_name.upper()}] = { .len = sizeof(struct ovs_key__${header_name}) }, \
+//:: #endfor
+ [OVS_KEY_ATTR_VALID] = { .len = sizeof(struct ovs_key_valid) }, \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_FLOW_KEY_FROM_FLOW \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ struct ovs_key__${header_name} *_${header_name}; \
+ _${header_name} = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR__${header_name.upper()}, sizeof *_${header_name}); \
+ get__${header_name}_key(data, _${header_name}); \
+ \
+//:: #endfor
+ struct ovs_key_valid *valid; \
+ valid = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_VALID, sizeof *valid); \
+ get_valid_key(data, valid); \
+ \
+
+/* -- Used in lib/odp-util.c -- */
+#define OVS_FLOW_KEY_TO_FLOW \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR__${header_name.upper()})) { \
+ const struct ovs_key__${header_name} *_${header_name}; \
+ \
+ _${header_name} = nl_attr_get(attrs[OVS_KEY_ATTR__${header_name.upper()}]); \
+ put__${header_name}_key(_${header_name}, flow); \
+ if (is_mask) { \
+ expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR__${header_name.upper()}; \
+ } \
+ } \
+ if (!is_mask) { \
+ expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR__${header_name.upper()}; \
+ } \
+ \
+//:: #endfor
+ if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VALID)) { \
+ const struct ovs_key_valid *valid; \
+ \
+ valid = nl_attr_get(attrs[OVS_KEY_ATTR_VALID]); \
+ put_valid_key(valid, flow); \
+ if (is_mask) { \
+ expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_VALID; \
+ } \
+ } \
+ if (!is_mask) { \
+ expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_VALID; \
+ } \
+ \
+
+#endif /* OVS_LIB_ODP_UTIL_C_H */
new file mode 100644
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_PACKETS_C_H
+#define OVS_LIB_PACKETS_C_H 1
+
+//:: # NOTE: here we can benefit from annotations. For example, we can provide
+//:: # annotations in P4 to specify which fields can be set in the datapath.
+//::
+/* -- Used in lib/packets.c -- */
+#define OVS_HDR_DEFS \
+//:: for header_name in ordered_header_instances_regular:
+ void packet_set__${header_name}( \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ uint8_t ${field_name}, \
+//:: elif bit_width == 16:
+ ovs_be16 ${field_name}, \
+//:: elif bit_width == 32:
+ ovs_be32 ${field_name}, \
+//:: elif bit_width == 64:
+ ovs_be64 ${field_name}, \
+//:: else:
+ struct ${field_name}_t ${field_name}, \
+//:: #endif
+//:: #endfor
+ struct dp_packet *packet) \
+ { \
+ struct _${header_name}_header *_${header_name} = dp_packet_${header_name}(packet); \
+ \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+ _${header_name}->${field_name} = ${field_name}; \
+//:: #endfor
+ } \
+ \
+//:: #endfor
+//::
+ void packet_set_valid( \
+//:: for header_name in ordered_header_instances_regular:
+ uint8_t _${header_name}_valid, \
+//:: #endfor
+ struct dp_packet *packet) \
+ { \
+//:: for header_name in ordered_header_instances_regular:
+ packet->_${header_name}_valid = _${header_name}_valid; \
+//:: #endfor
+ } \
+ \
+
+#endif /* OVS_LIB_PACKETS_C_H */
new file mode 100644
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_LIB_PACKETS_H_H
+#define OVS_LIB_PACKETS_H_H 1
+
+//:: # NOTE: here we can benefit from annotations. For example, we can provide
+//:: # annotations in P4 to specify which fields can be set in the datapath.
+//::
+/* -- Used in lib/packets.h -- */
+#define OVS_HDR_DECLS \
+//:: for header_name in ordered_header_instances_regular:
+ void packet_set__${header_name}( \
+//:: for field_name, bit_width in ordered_header_instances_non_virtual_field__name_width[header_name]:
+//:: if bit_width == 8:
+ uint8_t ${field_name}, \
+//:: elif bit_width == 16:
+ ovs_be16 ${field_name}, \
+//:: elif bit_width == 32:
+ ovs_be32 ${field_name}, \
+//:: elif bit_width == 64:
+ ovs_be64 ${field_name}, \
+//:: else:
+//:: # NOTE: we assume that all fields are, at least, byte aligned.
+ struct ${field_name}_t ${field_name}, \
+//:: #endif
+//:: #endfor
+ struct dp_packet *packet); \
+ \
+//:: #endfor
+ void packet_set_valid( \
+//:: for header_name in ordered_header_instances_regular:
+ uint8_t _${header_name}_valid, \
+//:: #endfor
+ struct dp_packet *packet); \
+ \
+
+#endif /* OVS_LIB_PACKETS_H_H */
new file mode 100644
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H
+#define OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H 1
+
+/* -- Called in ofproto/ofproto-dpif-sflow.h -- */
+#define OVS_SFLOW_READ_SET_ACTION_CASES \
+//:: # TODO: remove metadata that is not touched in the parser.
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ break; \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: \
+ break; \
+ \
+
+#endif /* OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H */
new file mode 100644
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H
+#define OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H 1
+
+/* -- Called in ofproto/ofproto-dpif-sflow.h -- */
+#define OVS_SFLOW_READ_SET_ACTION_CASES \
+//:: for header_name in ordered_header_instances_non_virtual:
+//:: if header_name == "standard_metadata" or header_name == "intrinsic_metadata":
+//:: continue
+//:: #endif
+ case OVS_KEY_ATTR__${header_name.upper()}: \
+ break; \
+//:: #endfor
+ case OVS_KEY_ATTR_VALID: \
+ break; \
+ \
+
+#endif /* OVS_OFPROTO_OFPROTO_DPIF_SFLOW_C_H */
@@ -1113,6 +1113,79 @@ def render_dict_populate_registers(render_dict, hlir):
register_info[name] = r_info
render_dict["register_info"] = register_info
+# @OVS:
+def render_dict_align_fields(render_dict):
+ render_dict['aligned_field_info'] = {}
+ aligned_field_info = render_dict['aligned_field_info']
+
+ field_info = render_dict['field_info']
+ header_info = render_dict['header_info']
+ ordered_header_instances_all = render_dict['ordered_header_instances_all']
+
+ for header_name in ordered_header_instances_all:
+ header = header_info[header_name]
+
+ field_names = []
+ run_bit_width = 0
+ for field_name in header['fields']:
+ bit_width = field_info[field_name]['bit_width']
+
+ run_bit_width += bit_width
+ if run_bit_width % 8 == 0:
+ if field_names:
+ # NOTE: we are assuming that smaller fields (i.e., less than a byte)
+ # combine together to align on a byte boundary.
+ if run_bit_width <= 1024:
+ field_names += [field_name]
+
+ cumm_bit_width = sum([field_info[f]['bit_width'] for f in field_names])
+ trunc_field_names = [f[len(header_name) + 1:] for f in field_names]
+ aligned_field_name = header_name + '_' + reduce(lambda x, y: x + '_' + y, trunc_field_names)
+
+ run_bit_width = 0
+ field_names.reverse()
+ for field_name in field_names:
+ bit_width = field_info[field_name]['bit_width']
+ # TODO: this might break for fields > 64 bits, look into this.
+ mask = (2 ** bit_width - 1) << run_bit_width
+ aligned_field_info[field_name] = {"name": aligned_field_name,
+ "bit_width": cumm_bit_width,
+ "mask": mask,
+ "bit_offset_hdr": run_bit_width}
+
+ run_bit_width += bit_width
+ else:
+ assert(False)
+ else:
+ aligned_field_name = header_name + '_' + field_name[len(header_name) + 1:]
+
+ aligned_field_info[field_name] = {"name": aligned_field_name,
+ "bit_width": bit_width,
+ "mask": 0,
+ "bit_offset_hdr": 0}
+ run_bit_width = 0
+ field_names = []
+ else:
+ field_names += [field_name]
+
+# @OVS:
+def render_dict_ordered_field_and_header_instances_non_virtual__name_width(render_dict):
+ render_dict["ordered_field_instances_non_virtual__name_width"] = []
+ render_dict["ordered_header_instances_non_virtual_field__name_width"] = {}
+
+ for header_name in render_dict["ordered_header_instances_non_virtual"]:
+ render_dict["ordered_header_instances_non_virtual_field__name_width"][header_name] = []
+ proc_fields = []
+ for field_name in render_dict["header_info"][header_name]["fields"]:
+ bit_width = render_dict["aligned_field_info"][field_name]["bit_width"]
+ field_name = render_dict["aligned_field_info"][field_name]["name"]
+ if field_name in proc_fields:
+ continue
+ proc_fields += [field_name]
+ render_dict["ordered_field_instances_non_virtual__name_width"] += [(field_name, bit_width)]
+ render_dict["ordered_header_instances_non_virtual_field__name_width"][header_name] += [(field_name,
+ bit_width)]
+
def get_type(byte_width):
if byte_width == 1:
return "uint8_t"
@@ -1171,6 +1244,10 @@ def render_dict_create(hlir,
render_dict_populate_meters(render_dict, hlir)
render_dict_populate_registers(render_dict, hlir)
+ # @OVS:
+ render_dict_align_fields(render_dict)
+ render_dict_ordered_field_and_header_instances_non_virtual__name_width(render_dict)
+
if hlir.p4_egress_ptr:
render_dict["egress_entry_table"] = get_table_name(hlir.p4_egress_ptr)
else: