├── README ├── p4c_bm ├── tenjin │ ├── __init__.py │ └── util.py ├── templates │ ├── .gitignore │ ├── thrift │ │ ├── devport_mgr_pd_rpc.thrift │ │ ├── res.thrift │ │ ├── mc_pd_rpc.thrift │ │ └── conn_mgr_pd_rpc.thrift │ ├── src │ │ ├── conditionals.h │ │ ├── checksums.h │ │ ├── calculations.h │ │ ├── pre_internal.h │ │ ├── pkt_manager.h │ │ ├── queuing.h │ │ ├── mirroring_internal.h │ │ ├── pipeline.c │ │ ├── portmanager.h │ │ ├── tcam_cache.h │ │ ├── actions.h │ │ ├── pd_devport_mgr.c │ │ ├── value_set.h │ │ ├── field_list.c │ │ ├── lf.h │ │ ├── metadata_recirc.h │ │ ├── parser.h │ │ ├── field_list.h │ │ ├── metadata_utils.h │ │ ├── pipeline.h │ │ ├── rmt_internal.h │ │ ├── action_profiles.h │ │ ├── devport_mgr_pd_rpc_server.ipp │ │ ├── rmt.c │ │ ├── pd_ms.h │ │ ├── deparser.h │ │ ├── pd_rpc_server.cpp │ │ ├── mc_pd_rpc_server.ipp │ │ ├── pd_static.c │ │ ├── value_set.c │ │ ├── metadata_recirc.c │ │ ├── pkt_manager.c │ │ ├── stateful.h │ │ ├── conditional_tables.c │ │ ├── portmanager.c │ │ ├── phv.c │ │ ├── primitives_arith.h │ │ ├── calculations.c │ │ ├── pd_pre.c │ │ ├── pg_int.h │ │ ├── metadata_utils.c │ │ ├── checksums.c │ │ ├── checksums_algos.h │ │ ├── tcam_cache.c │ │ ├── pd_ms.c │ │ ├── queuing.c │ │ └── phv.h │ └── inc │ │ ├── traffic_manager.h │ │ ├── pd_rpc_server.h │ │ ├── pd_devport_mgr.h │ │ ├── pre.h │ │ ├── pd_pre.h │ │ ├── pg.h │ │ ├── rmt.h │ │ ├── mirroring.h │ │ └── pd_static.h ├── plugin │ ├── of │ │ ├── inc │ │ │ ├── openflow.h │ │ │ ├── pd_wrappers.h │ │ │ ├── ofpat_groups.h │ │ │ └── ofpat_pipeline.h │ │ └── src │ │ │ ├── ofpat_groups.c │ │ │ └── ofpat_state.h │ ├── p4c-plugin.mk │ ├── sai │ │ ├── inc │ │ │ ├── p4_sai_rpc_server.h │ │ │ └── sai.h │ │ ├── thrift │ │ │ └── p4_sai_rpc.thrift │ │ └── src │ │ │ ├── sai_static.c │ │ │ └── sai.c │ ├── openflow-plugin.mk │ └── sai-plugin.mk ├── __init__.py ├── util │ ├── __init__.py │ └── topo_sorting.py ├── globals.py ├── common.py ├── meta_config.json ├── primitives.json └── shell.py ├── MANIFEST.in ├── setup.py ├── README.md ├── .gitignore ├── tools └── gen_crc_tables.py └── p4c-bm.mk /README: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /p4c_bm/tenjin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /p4c_bm/templates/.gitignore: -------------------------------------------------------------------------------- 1 | *.cache 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include p4c_bm *.h 2 | recursive-include p4c_bm *.c 3 | recursive-include p4c_bm *.cpp 4 | recursive-include p4c_bm *.thrift 5 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/inc/openflow.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFPAT_H_ 2 | #define _OFPAT_H_ 3 | 4 | #include "p4_sim/ofpat_pipeline.h" 5 | #include "p4_sim/ofpat_groups.h" 6 | 7 | #endif /* _OFPAT_H_ */ 8 | -------------------------------------------------------------------------------- /p4c_bm/plugin/p4c-plugin.mk: -------------------------------------------------------------------------------- 1 | # command plugin makefile - includes others when enabled 2 | 3 | ifdef PLUGIN_SAI 4 | include ${P4FACTORY}/submodules/p4c-behavioral/p4c_bm/plugin/sai-plugin.mk 5 | GLOBAL_CFLAGS += -DENABLE_PLUGIN_SAI 6 | endif 7 | 8 | ifdef PLUGIN_OPENFLOW 9 | include ${P4FACTORY}/submodules/p4c-behavioral/p4c_bm/plugin/openflow-plugin.mk 10 | endif 11 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai/inc/p4_sai_rpc_server.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * C/C++ header file for calling server start function from C code 4 | */ 5 | 6 | #ifndef _P4_SAI_RPC_SERVER_H_ 7 | #define _P4_SAI_RPC_SERVER_H_ 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #define P4_SAI_RPC_SERVER_PORT 9091 14 | 15 | extern int start_p4_sai_rpc_server(int port); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | 22 | 23 | #endif /* _P4_SAI_RPC_SERVER_H_ */ 24 | -------------------------------------------------------------------------------- /p4c_bm/templates/thrift/devport_mgr_pd_rpc.thrift: -------------------------------------------------------------------------------- 1 | 2 | namespace py devport_mgr_pd_rpc 3 | namespace cpp devport_mgr_pd_rpc 4 | namespace c_glib devport_mgr_pd_rpc 5 | 6 | service devport_mgr { 7 | # Add port stuff here as well 8 | i32 devport_mgr_add_port (1: i32 dev_id, 2: i32 port_id, 9 | 3: i32 port_width, 4: bool autoneg_enable, 10 | 5: i32 port_speeds, 6: i32 port_fec_types, 11 | 7: i32 tx_pause, 8: i32 rx_pause); 12 | i32 devport_mgr_remove_port (1: i32 dev_id, 2: i32 port_id); 13 | } 14 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/inc/pd_wrappers.h: -------------------------------------------------------------------------------- 1 | #ifndef _PD_WRAPPERS_H_ 2 | #define _PD_WRAPPERS_H_ 3 | 4 | #include 5 | 6 | void 7 | openflow_init (Pvoid_t *adds, Pvoid_t *mods, Pvoid_t *defs, 8 | Pvoid_t *dels, Pvoid_t *read_bytes_hit, 9 | Pvoid_t *read_bytes_missed, Pvoid_t *read_packets_hit, 10 | Pvoid_t *read_packets_missed, Pvoid_t *per_flow_stats_bytes, 11 | Pvoid_t *per_flow_stats_packets); 12 | 13 | uint8_t 14 | num_openflow_tables (); 15 | 16 | #endif /* _PD_WRAPPERS_ */ 17 | -------------------------------------------------------------------------------- /p4c_bm/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /p4c_bm/util/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/conditionals.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_CONDITIONAL_H 18 | #define _RMT_CONDITIONAL_H 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name = 'p4c_behavioral', 6 | version = '0.9.4', 7 | install_requires=['pyyaml'], 8 | packages=['p4c_bm', 'p4c_bm/util', 'p4c_bm/tenjin',], 9 | include_package_data = True, 10 | package_data = { 11 | 'p4c_bm' : ['*.json'], 12 | }, 13 | entry_points = { 14 | 'console_scripts': [ 15 | 'p4c-behavioral=p4c_bm.shell:main', 16 | 'p4c-bm=p4c_bm.shell:main', 17 | ], 18 | }, 19 | author = 'Antonin BAS', 20 | author_email = 'antonin@barefootnetworks.com', 21 | description = 'p4c-behavioral: P4 compiler for the behavioral model target', 22 | license = '', 23 | url = 'http://www.barefootnetworks.com/', 24 | ) 25 | -------------------------------------------------------------------------------- /p4c_bm/globals.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # The parser prefix for tenjin processing 16 | tenjin_prefix = "//::" # Use // in prefix for C syntax processing 17 | 18 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/traffic_manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef TRAFFIC_MANAGER_H_ 18 | #define TRAFFIC_MANAGER_H_ 19 | 20 | int set_drop_tail_thr(const int thr); 21 | 22 | int set_packets_per_sec(const int pps); 23 | 24 | #endif // TRAFFIC_MANAGER_H_ 25 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/checksums.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_CHECKSUMS_H 18 | #define _RMT_CHECKSUMS_H 19 | 20 | #include "phv.h" 21 | 22 | int verify_checksums(phv_data_t *phv); 23 | 24 | void update_checksums(phv_data_t *phv); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/calculations.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | void calculations_init(void); 20 | 21 | typedef void (*CalculationFn)(phv_data_t *, uint8_t *); 22 | 23 | //:: for name, c_info in field_list_calculations.items(): 24 | void calculations_${name}(phv_data_t *phv, uint8_t *result); 25 | //:: #endfor 26 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pre_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PRE_INTERNAL_H 18 | #define _RMT_PRE_INTERNAL_H 19 | 20 | //:: if enable_pre: 21 | 22 | void mc_process_and_replicate(uint16_t mcast_group, uint8_t *metadata, int *metadata_recirc, buffered_pkt_t *b_pkt); 23 | void mc_pre_init(); 24 | 25 | //:: #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pkt_manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PKT_MANAGER_H 18 | #define _RMT_PKT_MANAGER_H 19 | 20 | #include 21 | 22 | int pkt_manager_receive(int ingress, void *pkt, int len); 23 | 24 | void pkt_manager_init(void); 25 | int pkt_manager_transmit(int egress, void *pkt, int len, uint64_t packet_id); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /p4c_bm/common.py: -------------------------------------------------------------------------------- 1 | def get_type(byte_width): 2 | if byte_width == 1: 3 | return "uint8_t" 4 | elif byte_width == 2: 5 | return "uint16_t" 6 | elif byte_width <= 4: 7 | return "uint32_t" 8 | else: 9 | return "uint8_t *" 10 | 11 | # match_fields is list of tuples (name, type) 12 | def gen_match_params(match_fields, field_info): 13 | params = [] 14 | for field, type in match_fields: 15 | if type == "valid": 16 | params += [(field + "_valid", 1)] 17 | continue 18 | f_info = field_info[field] 19 | bytes_needed = (f_info["bit_width"] + 7 ) / 8 20 | params += [(field, bytes_needed)] 21 | if type == "lpm": params += [(field + "_prefix_length", 2)] 22 | if type == "ternary": params += [(field + "_mask", bytes_needed)] 23 | return params 24 | 25 | def gen_action_params(names, byte_widths, _get_type = get_type): 26 | params = [] 27 | for name, width in zip(names, byte_widths): 28 | name = "action_" + name 29 | params += [(name, width)] 30 | return params 31 | 32 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/queuing.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_QUEUING_H 18 | #define _RMT_QUEUING_H 19 | 20 | #include "rmt_internal.h" 21 | #include "enums.h" 22 | 23 | #include 24 | 25 | void queuing_init(void); 26 | int queuing_receive(uint8_t *metadata, int *metadata_recirc, 27 | void *pkt, int len, uint64_t packet_id, 28 | pkt_instance_type_t instance_type); 29 | #endif 30 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/mirroring_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_MIRRORING_INTERNAL_H 18 | #define _RMT_MIRRORING_INTERNAL_H 19 | 20 | #include 21 | 22 | void mirroring_init(void); 23 | 24 | struct phv_data_t; 25 | int mirroring_receive(phv_data_t *phv, int *metadata_recirc, void *pkt, int len, 26 | uint64_t packet_id, pkt_instance_type_t instance_type); 27 | #endif 28 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/inc/ofpat_groups.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFPAT_GROUPS_H_ 2 | #define _OFPAT_GROUPS_H_ 3 | 4 | #include "loci/loci.h" 5 | #include "p4ofagent/openflow-spec1.3.0.h" 6 | 7 | /* Allocates a mc/lag group and installs flows in the ofpat pipeline 8 | * @param group_id Group id given by controller 9 | * @param buckets Action buckets given by controller 10 | * @param type Type of group (select, all, etc) 11 | */ 12 | void 13 | ofpat_group_alloc (uint32_t group_id, of_list_bucket_t *buckets, 14 | enum ofp_group_type type); 15 | 16 | /* Adds a group to the ingress group table 17 | * @param group_id Group id given by controller 18 | * @param type Type of group (select, all, etc) 19 | */ 20 | p4_pd_status_t 21 | ofpat_group_create (uint32_t group_id, enum ofp_group_type type); 22 | 23 | /* Deletes a group. 24 | * @param group_id Group id given by controller 25 | * @param type Type of group (select, all, etc) 26 | */ 27 | p4_pd_status_t 28 | ofpat_group_delete (uint32_t group_id, enum ofp_group_type type); 29 | 30 | #endif /* _OFPAT_GROUPS_H_ */ 31 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pipeline.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "pipeline.h" 21 | #include "phv.h" 22 | #include "rmt_internal.h" 23 | #include "fields.h" 24 | 25 | 26 | uint64_t get_timestamp() { 27 | struct timeval tv; 28 | gettimeofday(&tv,NULL); 29 | return tv.tv_sec*(uint64_t)1000000+tv.tv_usec; 30 | } 31 | 32 | void pipeline_destroy(pipeline_t *pipeline) { 33 | /* TODO */ 34 | return; 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | p4c-behavioral 2 | ======== 3 | 4 | ***This repository is 5 | deprecated. [p4c-behavioral](https://github.com/p4lang/p4c-behavioral) has 6 | been replaced by the 7 | [behavioral-model](https://github.com/p4lang/behavioral-model), aka 8 | bmv2. Please refer to this 9 | [README](https://github.com/p4lang/behavioral-model/blob/master/README.md) 10 | for more information. We have stopped providing maintenance for this 11 | repository and be advised that it may be removed altogether from Github after 12 | 12/31/2017. If you have concerns about transitioning to bmv2, please send an 13 | email to p4-dev@lists.p4.org.*** 14 | 15 | P4 compiler for the behavioral model (BM) target 16 | 17 | Pre-requisites: [p4-hlir](https://github.com/p4lang/p4-hlir) 18 | 19 | To install: 20 | ``` 21 | sudo python setup.py install 22 | ``` 23 | 24 | To run: 25 | ``` 26 | p4c-behavioral --gen-dir [--thrift] 27 | ``` 28 | 29 | For more info: 30 | ``` 31 | p4c-behavioral --help 32 | ``` 33 | 34 | p4c-bm is an alias for p4c-behavioral 35 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pd_rpc_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * C/C++ header file for calling server start function from C code 19 | */ 20 | 21 | #ifndef _P4_PD_RPC_SERVER_H_ 22 | #define _P4_PD_RPC_SERVER_H_ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #define P4_PD_RPC_SERVER_PORT 9090 29 | 30 | extern int start_p4_pd_rpc_server(int port); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | 37 | 38 | #endif /* _P4_PD_RPC_SERVER_H_ */ 39 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pd_devport_mgr.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _DEVPORT_MGR_H 18 | #define _DEVPORT_MGR_H 19 | 20 | #include "pd_static.h" 21 | 22 | p4_pd_status_t 23 | p4_pd_devport_mgr_add_port(uint32_t dev_id, uint32_t port_id, 24 | uint32_t port_width, bool autoneg_enable, 25 | uint32_t port_speeds, uint32_t port_fec_types, 26 | uint32_t tx_pause, uint32_t rx_pause); 27 | 28 | p4_pd_status_t 29 | p4_pd_devport_mgr_remove_port(uint32_t dev_id, uint32_t port_id); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /p4c_bm/templates/thrift/res.thrift: -------------------------------------------------------------------------------- 1 | namespace py res_pd_rpc 2 | namespace cpp res_pd_rpc 3 | namespace c_glib res_pd_rpc 4 | 5 | typedef i32 SessionHandle_t 6 | struct DevTarget_t { 7 | 1: required i32 dev_id; 8 | 2: required i16 dev_pipe_id; 9 | } 10 | 11 | enum P4LogLevel_t { 12 | P4_LOG_LEVEL_NONE = 0, # otherwise will it start from 1? 13 | P4_LOG_LEVEL_FATAL, 14 | P4_LOG_LEVEL_ERROR, 15 | P4_LOG_LEVEL_WARN, 16 | P4_LOG_LEVEL_INFO, 17 | P4_LOG_LEVEL_VERBOSE, 18 | P4_LOG_LEVEL_TRACE 19 | } 20 | 21 | enum PktGenTriggerType_t { 22 | TIMER_ONE_SHOT=0, 23 | TIMER_PERIODIC=1, 24 | PORT_DOWN=2, 25 | RECIRC_PATTERN=3 26 | } 27 | 28 | struct PktGenAppCfg_t { 29 | 1: required PktGenTriggerType_t trigger_type; 30 | 2: required i32 batch_count; 31 | 3: required i32 pkt_count; 32 | 4: required i32 pattern_key; 33 | 5: required i32 pattern_msk; 34 | 6: required i32 timer; 35 | 7: required i32 ibg; 36 | 8: required i32 ibg_jitter; 37 | 9: required i32 ipg; 38 | 10: required i32 ipg_jitter; 39 | 11: required i32 src_port; 40 | 12: required i32 src_port_inc; 41 | 13: required i32 buffer_offset; 42 | 14: required i32 length; 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ply generated files 2 | parsetab.py 3 | parser.out 4 | 5 | # Emacs temp files 6 | *~ 7 | \#*\# 8 | 9 | # Byte-compiled / optimized / DLL files 10 | __pycache__/ 11 | *.py[cod] 12 | 13 | # C extensions 14 | *.so 15 | 16 | # Distribution / packaging 17 | .Python 18 | env/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | lib/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .coverage 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | 64 | 65 | 66 | # Custom ignores 67 | dist/* 68 | build/* 69 | *.egg-info/* 70 | *TODO 71 | *.cache 72 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/portmanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef __PORTMANAGER_H 18 | #define __PORTMANAGER_H 19 | 20 | #include 21 | #include 22 | 23 | #define PORT_COUNT_PER_CHIP_MAX 456 24 | #define MAX_CHIPS 8 25 | #define PORT_COUNT_MAX (MAX_CHIPS * PORT_COUNT_PER_CHIP_MAX) + 1 26 | 27 | 28 | typedef void (*port_fn)(int, bool); 29 | void portmgr_init(void); 30 | void portmgr_cleanup(void); 31 | void portmgr_register_cb(port_fn func); 32 | p4_pd_status_t p4_port_add(uint32_t port); 33 | p4_pd_status_t p4_port_remove(uint32_t port); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /p4c_bm/plugin/openflow-plugin.mk: -------------------------------------------------------------------------------- 1 | 2 | BM_TENJIN_TARGET := ${BM_TENJIN_OUTPUT_NEWEST} 3 | 4 | BM_OF_PLUGIN_SRC_DIR := ${BM_BUILD_DIR}/plugin/of/src 5 | 6 | BM_OF_TEMPLATES_C := $(wildcard ${THIS_DIR}/p4c_bm/plugin/of/src/*.c) 7 | BM_OF_TENJIN_OUTPUT_C := $(addprefix ${BM_OF_PLUGIN_SRC_DIR}/, $(notdir ${BM_OF_TEMPLATES_C})) 8 | BM_OF_OBJS_C := $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_OF_TENJIN_OUTPUT_C})))) 9 | 10 | GLOBAL_CFLAGS += -I $(SUBMODULE_P4OFAGENT)/inc 11 | GLOBAL_CFLAGS += -I $(SUBMODULE_P4OFAGENT)/submodules/indigo/modules/indigo/module/inc 12 | GLOBAL_CFLAGS += -I $(SUBMODULE_P4OFAGENT)/submodules/indigo/submodules/loxigen-artifacts/loci/inc 13 | GLOBAL_CFLAGS += -I $(SUBMODULE_P4OFAGENT)/submodules/indigo/submodules/infra/modules/AIM/module/inc 14 | 15 | ${BM_OF_OBJS_C} : ${BM_OBJ_DIR}/%.o : ${BM_OF_PLUGIN_SRC_DIR}/%.c 16 | @echo " Compiling : openflow::$(notdir $<)" 17 | $(VERBOSE)gcc -o $@ $(COVERAGE_FLAGS) $(DEBUG_FLAGS) $(GLOBAL_INCLUDES) $(GLOBAL_CFLAGS) -I $(PUBLIC_INC_PATH) -MD -c $< 18 | 19 | # plugin target 20 | PLUGIN_LIBS += plugin-openflow.a 21 | $(LIB_DIR)/plugin-openflow.a: ${BM_OF_OBJS_C} ${BM_TENJIN_TARGET} 22 | ar -rc $@ $^ 23 | 24 | .NOTPARALLEL: 25 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/tcam_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_TCAM_CACHE_H 18 | #define _RMT_TCAM_CACHE_H 19 | 20 | #include 21 | 22 | typedef struct tcam_cache_s tcam_cache_t; 23 | 24 | tcam_cache_t *tcam_cache_create(int size, int key_size, int expiration_secs); 25 | 26 | void tcam_cache_destroy(tcam_cache_t *cache); 27 | 28 | int tcam_cache_lookup(tcam_cache_t *cache, uint8_t *key, void **data); 29 | 30 | int tcam_cache_insert(tcam_cache_t *cache, uint8_t *key, void *data); 31 | 32 | int tcam_cache_purge(tcam_cache_t *cache); 33 | 34 | void tcam_cache_invalidate(tcam_cache_t *cache); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/actions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_ACTIONS_H 18 | #define _RMT_ACTIONS_H 19 | 20 | #include 21 | 22 | #include "phv.h" 23 | 24 | /* Generic type for action functions, table entries will store a function 25 | pointer to the appropriate such function */ 26 | typedef void (*ActionFn)(phv_data_t *phv, void *action_data); 27 | 28 | //:: for action_name, action in action_info.items(): 29 | void action_${action_name} (phv_data_t *phv, void *action_data); 30 | //:: #endfor 31 | 32 | char *action_get_name(ActionFn fn); 33 | void action_dump_action_data(ActionFn fn, uint8_t *data, char *action_desc, int max_length); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_devport_mgr.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include "portmanager.h" 21 | 22 | 23 | p4_pd_status_t 24 | p4_pd_devport_mgr_add_port(uint32_t dev_id, 25 | uint32_t port_id, 26 | uint32_t port_width, 27 | bool autoneg_enable, 28 | uint32_t port_speeds, 29 | uint32_t port_fec_types, 30 | uint32_t tx_pause, 31 | uint32_t rx_pause) 32 | { 33 | dev_id = 0; 34 | return p4_port_add(port_id); 35 | } 36 | 37 | p4_pd_status_t 38 | p4_pd_devport_mgr_remove_port(uint32_t dev_id, uint32_t port_id) 39 | { 40 | dev_id = 0; 41 | return p4_port_remove(port_id); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/value_set.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_VALUE_SET_H 18 | #define _RMT_VALUE_SET_H 19 | 20 | #include 21 | 22 | #include "fields.h" 23 | 24 | //:: for name, vs_info in value_sets.items(): 25 | int value_set_${name}_contains(uint8_t *key); 26 | //:: #endfor 27 | 28 | //:: for name, vs_info in value_sets.items(): 29 | void *value_set_${name}_add(uint8_t *value, uint8_t *mask); 30 | //:: #endfor 31 | 32 | //:: for name, vs_info in value_sets.items(): 33 | int value_set_${name}_delete(void *value); 34 | //:: #endfor 35 | 36 | //:: for name, vs_info in value_sets.items(): 37 | void *value_set_${name}_lookup(uint8_t *value, uint8_t *mask); 38 | 39 | //:: #endfor 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/field_list.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "field_list.h" 18 | 19 | //:: for name, field_list in field_lists.items(): 20 | field_list_entry_t ${name}_entries[] = { 21 | //:: for type_, value in field_list: 22 | //:: if type_ == "field_ref": 23 | {FIELD_LIST_ENTRY_FIELD, {(rmt_header_instance_t)RMT_FIELD_INSTANCE_${value}}, 0}, // cannot be virtual 24 | //:: elif type_ == "header_ref": 25 | {FIELD_LIST_ENTRY_HEADER, {RMT_HEADER_INSTANCE_${value}}, 0}, // cannot be virtual 26 | //:: #endif 27 | //:: #endfor 28 | }; 29 | 30 | //:: #endfor 31 | 32 | field_list_t _rmt_field_lists[RMT_FIELD_LIST_COUNT + 1] = { 33 | {0, NULL}, 34 | //:: for name, field_list in field_lists.items(): 35 | //:: size = len(field_list) 36 | {${size}, ${name}_entries}, 37 | //:: #endfor 38 | {0, NULL} 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /p4c_bm/meta_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta_mappings": { 3 | "standard_metadata" : { 4 | "ingress_port" : "standard_metadata_ingress_port", 5 | "egress_port" : "standard_metadata_egress_port", 6 | "clone_spec" : "standard_metadata_clone_spec", 7 | "egress_spec" : "standard_metadata_egress_spec", 8 | "packet_length" : "standard_metadata_packet_length", 9 | "instance_type" : "standard_metadata_instance_type" 10 | }, 11 | "intrinsic_metadata" : { 12 | "ingress_global_timestamp": "intrinsic_metadata_ingress_global_tstamp", 13 | "enq_qdepth": "intrinsic_metadata_enq_qdepth", 14 | "enq_timestamp": "intrinsic_metadata_enq_tstamp", 15 | "enq_congest_stat": "intrinsic_metadata_enq_congest_stat", 16 | "deq_qdepth": "intrinsic_metadata_deq_qdepth", 17 | "deq_timedelta": "intrinsic_metadata_deq_timedelta", 18 | "deq_congest_stat": "intrinsic_metadata_deq_congest_stat", 19 | "deflect_on_drop": "intrinsic_metadata_deflect_on_drop", 20 | "deflection_flag": "intrinsic_metadata_deflection_flag", 21 | "lf_field_list": "intrinsic_metadata_lf_field_list" 22 | }, 23 | "pre_metadata" : { 24 | "eg_mcast_group": "intrinsic_metadata_mcast_grp", 25 | "replication_id": "intrinsic_metadata_egress_rid", 26 | "lag_hash": "intrinsic_metadata_mcast_hash" 27 | } 28 | }, 29 | "meta_carry" : [ 30 | "standard_metadata" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/lf.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_LF_H 18 | #define _RMT_LF_H 19 | 20 | #include 21 | #include "enums.h" 22 | #include "phv.h" 23 | 24 | //:: pd_prefix = ["p4_pd", p4_prefix] 25 | //:: lf_prefix = ["lf", p4_prefix] 26 | //:: lf_set_learning_timeout = "_".join(lf_prefix + ["set_learning_timeout"]) 27 | void 28 | ${lf_set_learning_timeout}(const long int usecs); 29 | 30 | //:: for lq in learn_quanta: 31 | p4_pd_status_t 32 | ${lq["lf_register_fn"]}(p4_pd_sess_hdl_t sess_hdl, ${lq["cb_fn_type"]} cb_fn, void *client_data); 33 | 34 | p4_pd_status_t 35 | ${lq["lf_deregister_fn"]}(p4_pd_sess_hdl_t sess_hdl); 36 | 37 | p4_pd_status_t 38 | ${lq["lf_notify_ack_fn"]}(p4_pd_sess_hdl_t sess_hdl, ${lq["msg_type"]} *digest_msg); 39 | //:: #endfor 40 | 41 | void lf_init(); 42 | 43 | int lf_receive(phv_data_t *phv, const rmt_field_list_t field_list); 44 | 45 | void lf_clean_all(); 46 | #endif /* _RMT_LF_H */ 47 | -------------------------------------------------------------------------------- /p4c_bm/templates/thrift/mc_pd_rpc.thrift: -------------------------------------------------------------------------------- 1 | include "res.thrift" 2 | 3 | namespace py mc_pd_rpc 4 | namespace cpp mc_pd_rpc 5 | namespace c_glib mc_pd_rpc 6 | 7 | typedef i32 McHandle_t 8 | 9 | service mc { 10 | # Multicast APIs. 11 | //:: if enable_pre: 12 | i32 mc_init (); 13 | res.SessionHandle_t mc_create_session (); 14 | i32 mc_destroy_session (1: res.SessionHandle_t sess_hdl); 15 | i32 mc_complete_operations(1: res.SessionHandle_t sess_hdl); 16 | McHandle_t mc_mgrp_create (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: i16 mgid); 17 | i32 mc_mgrp_destroy (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: McHandle_t grp_hdl); 18 | McHandle_t mc_node_create (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: i16 rid, 4: binary port_map, 5: binary lag_map); 19 | i32 mc_node_update (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: McHandle_t l1_hdl, 4: binary port_map, 5: binary lag_map); 20 | i32 mc_node_destroy (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: McHandle_t l1_hdl); 21 | i32 mc_associate_node (1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: McHandle_t grp_hdl, 4: McHandle_t l1_hdl); 22 | i32 mc_dissociate_node(1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: McHandle_t grp_hdl, 4: McHandle_t l1_hdl); 23 | i32 mc_set_lag_membership(1: res.SessionHandle_t sess_hdl, 2: i32 dev_id, 3: byte lag_index, 4: binary port_map); 24 | //:: #endif 25 | } 26 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/metadata_recirc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_METADATA_RECIRC_ 18 | #define _RMT_METADATA_RECIRC_ 19 | 20 | #include "enums.h" 21 | 22 | typedef struct metadata_recirc_set_s metadata_recirc_set_t; 23 | 24 | metadata_recirc_set_t *metadata_recirc_create(void); 25 | 26 | void metadata_recirc_add_field(metadata_recirc_set_t *set, 27 | rmt_field_instance_t field); 28 | 29 | void metadata_recirc_remove_field(metadata_recirc_set_t *set, 30 | rmt_field_instance_t field); 31 | 32 | void metadata_recirc_add_header(metadata_recirc_set_t *set, 33 | rmt_header_instance_t hdr); 34 | 35 | int *metadata_recirc_digest(metadata_recirc_set_t *set); 36 | 37 | metadata_recirc_set_t *metadata_recirc_init(int *data); 38 | 39 | void metadata_recirc_empty(metadata_recirc_set_t *set); 40 | 41 | int metadata_recirc_is_valid(metadata_recirc_set_t *set, 42 | rmt_field_instance_t field); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PARSER_H 18 | #define _RMT_PARSER_H 19 | 20 | #include 21 | 22 | #include "phv.h" 23 | #include "tables.h" 24 | 25 | #define BYTE_ROUND_UP(x) ((x + 7) >> 3) 26 | 27 | typedef ApplyTableFn (*ParseStateFn)(phv_data_t *phv, uint8_t *pkt); 28 | 29 | ApplyTableFn parser_parse_pkt(phv_data_t *phv, 30 | uint8_t *pkt, int len, 31 | ParseStateFn start); 32 | 33 | void parser_parse_metadata(phv_data_t *phv, 34 | uint8_t *metadata, int *metadata_recirc); 35 | 36 | /* parse states */ 37 | 38 | /* should include parse_state_start */ 39 | //:: for state_name, p_info in parse_states.items(): 40 | ApplyTableFn parse_state_${state_name}(phv_data_t *phv, uint8_t *pkt); 41 | //:: #endfor 42 | 43 | 44 | //:: for header_instance in ordered_header_instances_non_virtual: 45 | void _extract_${header_instance}(uint8_t *dst, uint8_t *hdr); 46 | //:: #endfor 47 | 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/field_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "enums.h" 20 | #include "phv.h" 21 | 22 | typedef enum field_list_entry_type_e { 23 | FIELD_LIST_ENTRY_FIELD, 24 | FIELD_LIST_ENTRY_HEADER, 25 | FIELD_LIST_ENTRY_UINT32, 26 | FIELD_LIST_ENTRY_BYTE_BUF, 27 | FIELD_LIST_ENTRY_FIELD_LIST, 28 | FIELD_LIST_ENTRY_PAYLOAD 29 | } field_list_entry_type_t; 30 | 31 | typedef struct field_list_s field_list_t; 32 | 33 | typedef struct field_list_entry_s { 34 | field_list_entry_type_t type; 35 | union { 36 | rmt_header_instance_t header; 37 | rmt_field_instance_t field; 38 | uint32_t uint32_value; 39 | byte_buf_t byte_buf_value; 40 | field_list_t *field_list; 41 | void *payload; 42 | } data; 43 | int size; 44 | } field_list_entry_t; 45 | 46 | struct field_list_s { 47 | int size; 48 | field_list_entry_t *entries; 49 | }; 50 | 51 | extern field_list_t _rmt_field_lists[RMT_FIELD_LIST_COUNT + 1]; 52 | 53 | static inline field_list_t *field_list_get(rmt_field_list_t field_list) { 54 | return &_rmt_field_lists[field_list]; 55 | } 56 | -------------------------------------------------------------------------------- /p4c_bm/primitives.json: -------------------------------------------------------------------------------- 1 | { 2 | "shift_left" : 3 | { 4 | "num_args" : 3, 5 | "args" : ["field", "value1", "value2"], 6 | "properties" : { 7 | "field" : { 8 | "type" : ["field"], 9 | "access" : "write" 10 | }, 11 | "value1" : { 12 | "type" : ["field", "int", "table_entry_data"], 13 | "access" : "read", 14 | "data_width" : "field" 15 | }, 16 | "value2" : { 17 | "type" : ["field", "int", "table_entry_data"], 18 | "access" : "read", 19 | "data_width" : "field" 20 | } 21 | } 22 | }, 23 | "shift_right" : 24 | { 25 | "num_args" : 3, 26 | "args" : ["field", "value1", "value2"], 27 | "properties" : { 28 | "field" : { 29 | "type" : ["field"], 30 | "access" : "write" 31 | }, 32 | "value1" : { 33 | "type" : ["field", "int", "table_entry_data"], 34 | "access" : "read", 35 | "data_width" : "field" 36 | }, 37 | "value2" : { 38 | "type" : ["field", "int", "table_entry_data"], 39 | "access" : "read", 40 | "data_width" : "field" 41 | } 42 | } 43 | }, 44 | "modify_field_rng_uniform" : 45 | { 46 | "num_args" : 3, 47 | "args" : ["dst", "begin", "end"], 48 | "properties" : { 49 | "dst" : { 50 | "type" : ["field"], 51 | "access" : "write" 52 | }, 53 | "begin" : { 54 | "type" : ["field", "int", "table_entry_data"], 55 | "access" : "read", 56 | "data_width" : "dst" 57 | }, 58 | "end" : { 59 | "type" : ["field", "int", "table_entry_data"], 60 | "access" : "read", 61 | "data_width" : "dst" 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/metadata_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_METADATA_UTILS_H 18 | #define _RMT_METADATA_UTILS_H 19 | 20 | void metadata_extract(uint8_t *dst, uint8_t *hdr, 21 | int *metadata_recirc); 22 | 23 | void metadata_dump(uint8_t *hdr, uint8_t *src); 24 | 25 | //:: for name, binding in metadata_name_map.items(): 26 | uint32_t metadata_get_${name}(uint8_t *metadata); 27 | 28 | void metadata_set_${name}(uint8_t *metadata, uint32_t value); 29 | 30 | //:: #endfor 31 | 32 | 33 | //:: if enable_intrinsic : 34 | //:: for name, binding in intrinsic_metadata_name_map.items(): 35 | uint32_t metadata_get_${name}(uint8_t *metadata); 36 | 37 | void metadata_set_${name}(uint8_t *metadata, uint32_t value); 38 | 39 | //:: #endfor 40 | //:: #endif 41 | 42 | //:: if enable_pre : 43 | //:: for name, binding in pre_metadata_name_map.items(): 44 | uint32_t metadata_get_${name}(uint8_t *metadata); 45 | 46 | void metadata_set_${name}(uint8_t *metadata, uint32_t value); 47 | 48 | //:: #endfor 49 | //:: #endif 50 | 51 | //:: for name, binding in extra_metadata_name_map.items(): 52 | uint32_t metadata_get_${name}(uint8_t *metadata); 53 | 54 | void metadata_set_${name}(uint8_t *metadata, uint32_t value); 55 | 56 | //:: #endfor 57 | #endif 58 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pipeline.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PIPELINE_H 18 | #define _RMT_PIPELINE_H 19 | 20 | #include 21 | #include 22 | 23 | #include "parser.h" 24 | #include "deparser.h" 25 | #include "phv.h" 26 | #include "rmt_internal.h" 27 | #include "enums.h" 28 | 29 | #include 30 | 31 | #define CLONE_SPEC_FOR_DEFLECTED_TAIL_DROPS 0x0000FFFF 32 | 33 | typedef struct pipeline_s { 34 | char *name; 35 | circular_buffer_t *cb_in; 36 | ParseStateFn parse_state_start; 37 | ApplyTableFn table_entry_fn; 38 | DeparseFn deparse_fn; 39 | pthread_t processing_thread; 40 | phv_data_t *phv; 41 | } pipeline_t; 42 | 43 | int ingress_pipeline_init(void); 44 | int ingress_pipeline_receive(int ingress, 45 | uint8_t *metadata, int *metadata_recirc, 46 | void *pkt, int len, uint64_t packet_id, 47 | pkt_instance_type_t instance_type); 48 | 49 | int egress_pipeline_init(void); 50 | int egress_pipeline_receive(int egress, 51 | uint8_t *metadata, int *metadata_recirc, 52 | void *pkt, int len, uint64_t packet_id, 53 | pkt_instance_type_t instance_type); 54 | 55 | void pipeline_destroy(pipeline_t *pipeline); 56 | 57 | uint64_t get_timestamp(); 58 | 59 | int egress_pipeline_count(int egress); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/rmt_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_RMT_INTERNAL_H 18 | #define _RMT_RMT_INTERNAL_H 19 | 20 | #include 21 | #include 22 | 23 | #include "p4_sim/rmt.h" 24 | #include "enums.h" 25 | 26 | #define NB_THREADS_PER_PIPELINE 8 27 | #define NB_THREADS (2 * NB_THREADS_PER_PIPELINE) 28 | 29 | #ifdef DEBUG 30 | #define RMT_LOG(level, ...) \ 31 | do { \ 32 | if(rmt_instance->logger && level <= rmt_instance->log_level) { \ 33 | rmt_instance->logger(__VA_ARGS__); \ 34 | } \ 35 | } \ 36 | while(0) 37 | #else 38 | #define RMT_LOG(level, ...) ; 39 | #endif 40 | 41 | #define RMT_PRINT(...) \ 42 | do { \ 43 | rmt_instance->logger(__VA_ARGS__); \ 44 | } \ 45 | while(0) 46 | 47 | 48 | #define RMT_LOG_LEVEL (rmt_instance->log_level) 49 | 50 | typedef struct rmt_instance_s { 51 | p4_logging_f logger; 52 | p4_log_level_t log_level; 53 | rmt_transmit_vector_f tx_fn; 54 | } rmt_instance_t; 55 | 56 | extern rmt_instance_t *rmt_instance; 57 | 58 | /* TODO: define a different format for each queue (cb) ? */ 59 | 60 | typedef struct buffered_pkt_s { 61 | pkt_instance_type_t instance_type; 62 | uint8_t *pkt_data; 63 | int pkt_len; 64 | uint64_t pkt_id; 65 | } buffered_pkt_t; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/action_profiles.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_ACTION_PROFILES_H 18 | #define _RMT_ACTION_PROFILES_H 19 | 20 | #include "phv.h" 21 | #include "enums.h" 22 | 23 | #include 24 | #include 25 | 26 | #define ACT_PROF_DEFAULT_INIT_SIZE 16384 // entries 27 | 28 | void action_profiles_init(void); 29 | 30 | //:: for act_prof, ap_info in action_profiles.items(): 31 | int action_profiles_add_entry_${act_prof}(char *action_data); 32 | //:: #endfor 33 | 34 | //:: for act_prof, ap_info in action_profiles.items(): 35 | int action_profiles_delete_entry_${act_prof}(int entry_index); 36 | //:: #endfor 37 | 38 | //:: for act_prof, ap_info in action_profiles.items(): 39 | int action_profiles_modify_entry_${act_prof}(int entry_index, char *action_data); 40 | //:: #endfor 41 | 42 | //:: for act_prof, ap_info in action_profiles.items(): 43 | char *action_profiles_get_data_${act_prof}(phv_data_t *phv, char *id); 44 | //:: #endfor 45 | 46 | int action_profiles_create_group(rmt_act_prof_t act_prof_e); 47 | int action_profiles_delete_group(rmt_act_prof_t act_prof_e, int index); 48 | int action_profiles_add_member_to_group(rmt_act_prof_t act_prof_e, 49 | int grp_index, int mbr_index); 50 | int action_profiles_delete_member_from_group(rmt_act_prof_t act_prof_e, 51 | int grp_index, int mbr_index); 52 | 53 | void action_profiles_clean_all(void); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/devport_mgr_pd_rpc_server.ipp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | //:: pd_prefix = "p4_pd_" + p4_prefix + "_" 18 | //:: pd_static_prefix = "p4_pd_" 19 | //:: api_prefix = p4_prefix + "_" 20 | 21 | #include "devport_mgr.h" 22 | 23 | extern "C" { 24 | #include 25 | #include 26 | #include 27 | } 28 | 29 | using boost::shared_ptr; 30 | 31 | using namespace ::devport_mgr_pd_rpc; 32 | 33 | class devport_mgrHandler : virtual public devport_mgrIf { 34 | public: 35 | devport_mgrHandler() { 36 | } 37 | //:: name = "devport_mgr_add_port" 38 | //:: pd_name = pd_static_prefix + name 39 | 40 | int32_t ${name}(const int32_t dev_id, 41 | const int32_t port_id, 42 | const int32_t port_width, 43 | const bool autoneg_enable, 44 | const int32_t port_speeds, 45 | const int32_t port_fec_types, 46 | const int32_t tx_pause, 47 | const int32_t rx_pause) { 48 | 49 | return ${pd_name}(dev_id, 50 | port_id, 51 | port_width, 52 | autoneg_enable, 53 | port_speeds, 54 | port_fec_types, 55 | tx_pause, 56 | rx_pause); 57 | } 58 | 59 | //:: name = "devport_mgr_remove_port" 60 | //:: pd_name = pd_static_prefix + name 61 | int32_t ${name}(const int32_t dev_id, const int32_t port_id) { 62 | return ${pd_name}(dev_id, port_id); 63 | } 64 | 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/rmt.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "phv.h" 22 | #include "parser.h" 23 | #include "deparser.h" 24 | #include "tables.h" 25 | #include "action_profiles.h" 26 | #include "enums.h" 27 | #include "p4_sim/pd.h" 28 | #include "p4_sim/rmt.h" 29 | #include "rmt_internal.h" 30 | #include "pkt_manager.h" 31 | #include "calculations.h" 32 | #include "portmanager.h" 33 | #include "pg_int.h" 34 | 35 | rmt_instance_t *rmt_instance; 36 | 37 | void rmt_init(void) { 38 | rmt_instance = malloc(sizeof(rmt_instance_t)); 39 | memset(rmt_instance, 0, sizeof(rmt_instance_t)); 40 | 41 | portmgr_init(); 42 | pktgen_init(); 43 | tables_init(); 44 | action_profiles_init(); 45 | stateful_init(); 46 | calculations_init(); 47 | 48 | pkt_manager_init(); 49 | } 50 | 51 | int rmt_process_pkt(p4_port_t ingress, void *pkt, int len) { 52 | RMT_LOG(P4_LOG_LEVEL_VERBOSE, "new packet, len : %d, ingress : %d\n", 53 | len, ingress); 54 | 55 | return pkt_manager_receive(ingress, pkt, len); 56 | } 57 | 58 | void rmt_logger_set(p4_logging_f log_fn) { 59 | rmt_instance->logger = log_fn; 60 | } 61 | 62 | void rmt_log_level_set(p4_log_level_t level) { 63 | rmt_instance->log_level = level; 64 | } 65 | 66 | p4_log_level_t rmt_log_level_get() { 67 | return rmt_instance->log_level; 68 | } 69 | 70 | void rmt_transmit_register(rmt_transmit_vector_f tx_fn) { 71 | rmt_instance->tx_fn = tx_fn; 72 | } 73 | 74 | void rmt_cleanup(void) { 75 | portmgr_cleanup(); 76 | pktgen_cleanup(); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/inc/ofpat_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFPAT_PIPELINE_H_ 2 | #define _OFPAT_PIPELINE_H_ 3 | 4 | /* 5 | * Ofpat pipeline datatypes and API 6 | */ 7 | 8 | #include 9 | #include "p4ofagent/openflow-spec1.3.0.h" 10 | 11 | /* Indexes pipeline in pipeline state */ 12 | typedef struct ofpat_pipeline_key { 13 | uint64_t *index; 14 | uint32_t *group_id; 15 | uint16_t *egr_port; 16 | } ofpat_pipeline_key_t; 17 | 18 | /* Fill in pipeline key */ 19 | void 20 | ofpat_pipeline_key_new (uint64_t *index, uint32_t *group_id, 21 | uint16_t *egr_port, ofpat_pipeline_key_t *key); 22 | 23 | /* Generic match struct for pipeline entries */ 24 | typedef struct ofpat_pipeline_match { 25 | uint32_t index; 26 | uint32_t index_mask; 27 | uint32_t group_id; 28 | uint32_t group_id_mask; 29 | uint16_t egr_port; 30 | uint16_t egr_port_mask; 31 | } ofpat_match_t; 32 | 33 | /* Fill in match struct */ 34 | void 35 | ofpat_match_get (ofpat_match_t *ms, ofpat_pipeline_key_t *key); 36 | 37 | /* Returns pointer to action arg val indexed by t 38 | * @param aargs Datastructure holding action arg vals 39 | * @param t The action type 40 | */ 41 | void* 42 | ofpat_action_get (Pvoid_t *aargs, enum ofp_action_type t); 43 | 44 | /* Adds an OFPAT pipeline 45 | * @param bmap Bitmap of actions to add 46 | * @param key Used to index pipeline 47 | * @param aargs OFPAT arguments, indexed by OFPAT enum vals 48 | */ 49 | p4_pd_status_t 50 | ofpat_pipeline_add (uint32_t bmap, ofpat_pipeline_key_t *key, 51 | Pvoid_t *aargs); 52 | 53 | /* Modifies an OFPAT pipeline 54 | * @param bmap Bitmap of actions to add 55 | * @param key Used to index pipeline 56 | * @param aargs OFPAT arguments, indexed by OFPAT enum vals 57 | */ 58 | p4_pd_status_t 59 | ofpat_pipeline_mod (uint32_t bmap, ofpat_pipeline_key_t *key, 60 | Pvoid_t *aargs); 61 | 62 | /* Sets default entries to nop */ 63 | p4_pd_status_t 64 | ofpat_pipeline_set_default_nop (); 65 | 66 | /* Deletes an OFPAT pipeline. 67 | * @param key Used to get the pipeline 68 | */ 69 | p4_pd_status_t 70 | ofpat_pipeline_del (ofpat_pipeline_key_t *key); 71 | 72 | #endif /* _OFPAT_PIPELINE_H_ */ 73 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai-plugin.mk: -------------------------------------------------------------------------------- 1 | 2 | BM_TENJIN_TARGET := ${BM_TENJIN_OUTPUT_NEWEST} 3 | 4 | BM_BUILD_PLUGIN_SRC_DIR := ${BM_BUILD_DIR}/plugin/sai/src 5 | BM_BUILD_PLUGIN_THRIFT_DIR := ${BM_BUILD_DIR}/plugin/sai/thrift 6 | ${BM_BUILD_PLUGIN_SRC_DIR}/p4_sai_rpc_types.h : ${BM_BUILD_PLUGIN_THRIFT_DIR}/p4_sai_rpc.thrift # ${BM_TENJIN_TARGET} 7 | thrift --gen cpp --out ${BM_BUILD_PLUGIN_SRC_DIR} $< 8 | 9 | ${BM_PLUGIN_THRIFT_OUTPUT_CPP} : ${BM_BUILD_PLUGIN_SRC_DIR}/p4_sai_rpc_types.h 10 | 11 | THRIFT_INPUT_FILES := ${BM_BUILD_PLUGIN_THRIFT_DIR}/p4_sai_rpc.thrift 12 | THRIFT_DEP_FILES := ${BM_BUILD_PLUGIN_THRIFT_DIR}/p4_sai_rpc.thrift 13 | THRIFT_SERVICE_NAMES := p4_sai_rpc 14 | include ${MAKEFILES_DIR}/thrift-py.mk 15 | 16 | ${BM_BUILD_PLUGIN_THRIFT_DIR}/p4_sai_rpc.thrift: $(BM_TENJIN_OUTPUT_OLDEST) 17 | 18 | BM_TEMPLATES_SAI_C := $(addprefix ${BM_BUILD_PLUGIN_SRC_DIR}/, sai.c sai_templ.c sai_static.c) 19 | BM_TEMPLATES_SAI := ${BM_TEMPLATES_SAI_C} ${BM_TEMPLATES_SAI_CPP} 20 | BM_TENJIN_OUTPUT_SAI_C := $(addprefix ${BM_BUILD_PLUGIN_SRC_DIR}/, $(notdir ${BM_TEMPLATES_SAI_C})) 21 | BM_SAI_OBJS_C := $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_TENJIN_OUTPUT_SAI_C})))) 22 | ${BM_SAI_OBJS_C} : ${BM_OBJ_DIR}/%.o : ${BM_BUILD_PLUGIN_SRC_DIR}/%.c ${BM_TEMPLATES_SAI} 23 | @echo " Compiling : sai::$(notdir $<)" 24 | $(VERBOSE)gcc -o $@ $(COVERAGE_FLAGS) $(DEBUG_FLAGS) $(GLOBAL_INCLUDES) $(GLOBAL_CFLAGS) -I $(PUBLIC_INC_PATH) -MD -c $< 25 | 26 | 27 | BM_TEMPLATES_SAI_CPP := $(addprefix ${BM_BUILD_PLUGIN_SRC_DIR}/, p4_sai_rpc_constants.cpp p4_sai_rpc_types.cpp p4_sai_rpc_server.cpp sai_p4_sai.cpp) 28 | BM_TENJIN_OUTPUT_SAI_CPP := $(addprefix ${BM_BUILD_PLUGIN_SRC_DIR}/, $(notdir ${BM_TEMPLATES_SAI_CPP})) 29 | BM_SAI_OBJS_CPP := $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_TENJIN_OUTPUT_SAI_CPP})))) 30 | 31 | ${BM_SAI_OBJS_CPP} : ${BM_OBJ_DIR}/%.o : ${BM_BUILD_PLUGIN_SRC_DIR}/%.cpp ${BM_TEMPLATES_SAI} 32 | @echo " Compiling : sai::$(notdir $<)" 33 | $(VERBOSE)g++ -o $@ $(COVERAGE_FLAGS) $(DEBUG_FLAGS) $(GLOBAL_INCLUDES) -I ${PUBLIC_INC_PATH} -MD -c $< 34 | 35 | # plugin target 36 | $(LIB_DIR)/plugin-sai.a: ${BM_PLUGIN_THRIFT_OUTPUT_CPP} ${BM_BUILD_PLUGIN_SRC_DIR}/p4_sai_rpc_types.h ${BM_SAI_OBJS_C} ${BM_SAI_OBJS_CPP} 37 | ar -rc $@ $^ 38 | 39 | .NOTPARALLEL: 40 | -------------------------------------------------------------------------------- /p4c_bm/templates/thrift/conn_mgr_pd_rpc.thrift: -------------------------------------------------------------------------------- 1 | include "res.thrift" 2 | 3 | namespace py conn_mgr_pd_rpc 4 | namespace cpp conn_mgr_pd_rpc 5 | namespace c_glib conn_mgr_pd_rpc 6 | 7 | 8 | service conn_mgr { 9 | # Test echo interface 10 | void echo(1:string s); 11 | 12 | void init(); 13 | 14 | void cleanup(); 15 | 16 | res.SessionHandle_t client_init(); 17 | 18 | i32 client_cleanup(1:res.SessionHandle_t sess_hdl); 19 | 20 | i32 begin_txn(1:res.SessionHandle_t sess_hdl, 2:bool isAtomic, 3:bool isHighPri); 21 | 22 | i32 verify_txn(1:res.SessionHandle_t sess_hdl); 23 | 24 | i32 abort_txn(1:res.SessionHandle_t sess_hdl); 25 | 26 | i32 commit_txn(1:res.SessionHandle_t sess_hdl, 2:bool hwSynchronous); 27 | 28 | i32 complete_operations(1:res.SessionHandle_t sess_hdl); 29 | 30 | # control logging 31 | void rmt_log_level_set(1:res.P4LogLevel_t log_level); 32 | res.P4LogLevel_t rmt_log_level_get(); 33 | 34 | i32 recirculation_enable(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 35 | i32 recirculation_disable(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 36 | i32 pktgen_enable(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 37 | i32 pktgen_disable(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 38 | i32 pktgen_enable_recirc_pattern_matching(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 39 | i32 pktgen_disable_recirc_pattern_matching(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 40 | i32 pktgen_clear_port_down(1:res.SessionHandle_t sess_hdl, 2:i32 dev, 3:i32 port); 41 | 42 | i32 pktgen_cfg_app(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id, 4:res.PktGenAppCfg_t cfg); 43 | 44 | i32 pktgen_app_enable(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id); 45 | i32 pktgen_app_disable(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id); 46 | i32 pktgen_write_pkt_buffer(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 offset, 4:i32 size, 5:binary buf); 47 | i64 pktgen_get_batch_counter(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id); 48 | i64 pktgen_get_pkt_counter(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id); 49 | i64 pktgen_get_trigger_counter(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 app_id); 50 | 51 | i32 set_meter_time(1:res.SessionHandle_t sess_hdl, 2:res.DevTarget_t dev_tgt, 3:i32 meter_time_disable); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /tools/gen_crc_tables.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | crc_ccitt = {"polynomial": 0x1021, 4 | "width": 16, 5 | "initial_remainder": 0xFFFF, 6 | "final_xor_value": 0x0000, 7 | "reflect_data": False, 8 | "reflect_remaider": False, 9 | "check_value": 0x29B1} 10 | 11 | crc_32 = {"polynomial": 0x04C11DB7, 12 | "width": 32, 13 | "initial_remainder": 0xFFFFFFFF, 14 | "final_xor_value": 0xFFFFFFFF, 15 | "reflect_data": True, 16 | "reflect_remaider": True, 17 | "check_value": 0xCBF43926} 18 | 19 | crc_16 = {"polynomial": 0x8005, 20 | "width": 16, 21 | "initial_remainder": 0x0000, 22 | "final_xor_value": 0x0000, 23 | "reflect_data": True, 24 | "reflect_remaider": True, 25 | "check_value": 0xBB3D} 26 | 27 | CRCs = {"crc16": crc_16, "crc32": crc_32, "crcCCITT": crc_ccitt} 28 | 29 | BYTES_PER_LINE = 16 30 | 31 | def get_c_type(width): 32 | if width == 16: return "uint16_t" 33 | elif width == 32: return "uint32_t" 34 | else: assert(False) 35 | 36 | def get_format_string(width): 37 | if width == 16: return "0x%0.4X" 38 | elif width == 32: return "0x%0.8X" 39 | else: assert(False); 40 | 41 | for crc, info in CRCs.items(): 42 | out = sys.stdout 43 | out.write("***************************************\n") 44 | out.write(crc + "\n") 45 | out.write("**********\n") 46 | 47 | table = [0 for i in xrange(256)] 48 | for dividend in xrange(256): 49 | remainder = dividend << (info["width"] - 8) 50 | for bit in xrange(8): 51 | if (remainder & (1 << (info["width"] - 1))): 52 | remainder = (remainder << 1) ^ info["polynomial"] 53 | else: 54 | remainder = (remainder << 1) 55 | table[dividend] = remainder % (1 << info["width"]) 56 | 57 | type_ = get_c_type(info["width"]) 58 | format_ = get_format_string(info["width"]) 59 | WORDS_PER_LINE = BYTES_PER_LINE / (info["width"] / 8) 60 | out.write(type_ + " table_" + crc + "[256] = {\n") 61 | for i in xrange(256): 62 | if i % WORDS_PER_LINE == 0: 63 | out.write(" ") 64 | out.write(format_ % table[i]) 65 | if i != 255: 66 | out.write(", ") 67 | if (i + 1) % WORDS_PER_LINE == 0: 68 | out.write("\n") 69 | out.write("};\n") 70 | out.write("***************************************\n") 71 | -------------------------------------------------------------------------------- /p4c_bm/tenjin/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # These are utility functions, some taken from bigcode/infra/sourcegen/util.py 4 | # 5 | 6 | import copy 7 | import types 8 | import sys 9 | import os 10 | import tenjin 11 | import json 12 | import yaml 13 | # import globals as gl 14 | 15 | class DotDict(dict): 16 | """ Access keys in a nested dictionary using dot notation """ 17 | 18 | def __getattr__(self, attr): 19 | item = self.get(attr, None) 20 | if type(item) == types.DictType: 21 | item = DotDict(item) 22 | return item 23 | 24 | __setattr__= dict.__setitem__ 25 | __delattr__= dict.__delitem__ 26 | 27 | # From loxi_utils.py 28 | def render_template(out, name, context, templates_dir, prefix = None): 29 | """ 30 | Render a template using tenjin. 31 | out: a file-like object 32 | name: name of the template 33 | context: dictionary of variables to pass to the template 34 | prefix: optional prefix for embedding (for other languages than python) 35 | """ 36 | 37 | # support "::" syntax 38 | pp = [ tenjin.PrefixedLinePreprocessor(prefix=prefix) 39 | if prefix else tenjin.PrefixedLinePreprocessor() ] 40 | # disable HTML escaping 41 | template_globals = { "to_str": str, "escape": str } 42 | engine = TemplateEngine(path=[templates_dir], pp=pp, cache = False) 43 | out.write(engine.render(name, context, template_globals)) 44 | 45 | class TemplateEngine(tenjin.Engine): 46 | def include(self, template_name, **kwargs): 47 | """ 48 | Tenjin has an issue with nested includes that use the same local 49 | variable names, because it uses the same context dict for each level of 50 | nesting. The fix is to copy the context. 51 | """ 52 | frame = sys._getframe(1) 53 | locals = frame.f_locals 54 | globals = frame.f_globals 55 | context = locals["_context"].copy() 56 | context.update(kwargs) 57 | template = self.get_template(template_name, context, globals) 58 | return template.render(context, globals, _buf=locals["_buf"]) 59 | 60 | def dump_render_dict(render_dict, out = sys.stdout): 61 | # output = json.dumps(render_dict) 62 | output = yaml.dump(render_dict) 63 | out.write(output) 64 | 65 | # _verbose = 1 66 | # def verbose_set(verbose): 67 | # # @fixme ensure verbose is a number 68 | # gl.args.verbosity = verbose 69 | 70 | # def log_msg(str): 71 | # if gl.args.verbosity: 72 | # sys.stderr.write(str) 73 | 74 | # def log_verbose(str): 75 | # if gl.args.verbosity > 1: 76 | # sys.stderr.write(str) 77 | 78 | def error(str): 79 | sys.stderr.write(str) 80 | os._exit(1) 81 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_ms.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PD_MS_H 18 | #define _RMT_PD_MS_H 19 | 20 | #include "actions.h" 21 | 22 | void p4_pd_ms_init(void); 23 | 24 | typedef ActionFn p4_pd_act_hdl_t; 25 | typedef struct p4_pd_ms_table_state_s p4_pd_ms_table_state_t; 26 | 27 | //:: _action_profiles = set() 28 | //:: for table, t_info in table_info.items(): 29 | //:: act_prof = t_info["action_profile"] 30 | //:: if act_prof is None: continue 31 | //:: if act_prof in _action_profiles: continue 32 | //:: _action_profiles.add(act_prof) 33 | extern p4_pd_ms_table_state_t ms_${act_prof}_state; 34 | //:: #endfor 35 | 36 | void p4_pd_ms_new_mbr(p4_pd_ms_table_state_t *state, uint8_t dev_id, 37 | p4_pd_mbr_hdl_t mbr_hdl); 38 | 39 | void p4_pd_ms_del_mbr(p4_pd_ms_table_state_t *state, uint8_t dev_id, 40 | p4_pd_mbr_hdl_t mbr_hdl); 41 | 42 | int p4_pd_ms_add_mbr_to_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 43 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_grp_hdl_t grp_hdl); 44 | 45 | int p4_pd_ms_del_mbr_from_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 46 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_grp_hdl_t grp_hdl); 47 | 48 | typedef void (*PDMSGrpFn)(uint8_t dev_id, 49 | p4_pd_mbr_hdl_t mbr_hdl, 50 | p4_pd_grp_hdl_t grp_hdl, 51 | void *aux); 52 | 53 | void p4_pd_ms_mbr_apply_to_grps(p4_pd_ms_table_state_t *state, uint8_t dev_id, 54 | p4_pd_mbr_hdl_t mbr_hdl, 55 | PDMSGrpFn grp_fn, void *aux); 56 | 57 | p4_pd_act_hdl_t p4_pd_ms_get_mbr_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 58 | p4_pd_mbr_hdl_t mbr_hdl); 59 | 60 | void p4_pd_ms_set_mbr_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 61 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_act_hdl_t act_hdl); 62 | 63 | p4_pd_act_hdl_t p4_pd_ms_get_grp_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 64 | p4_pd_grp_hdl_t grp_hdl); 65 | 66 | void p4_pd_ms_set_grp_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 67 | p4_pd_grp_hdl_t grp_hdl, p4_pd_act_hdl_t act_hdl); 68 | 69 | void p4_pd_ms_del_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 70 | p4_pd_grp_hdl_t grp_hdl); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/deparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_DEPARSER_H 18 | #define _RMT_DEPARSER_H 19 | 20 | #include 21 | 22 | typedef int (*DeparseFn)(phv_data_t *phv, uint8_t **pkt, int *len); 23 | 24 | int deparser_produce_pkt(phv_data_t *phv, uint8_t **pkt, int *len); 25 | 26 | int deparser_produce_metadata(phv_data_t *phv, uint8_t **metadata); 27 | 28 | void deparser_extract_digest(phv_data_t *phv, int *metadata_recirc, uint8_t *buffer, uint16_t *length); 29 | 30 | // |bit_offset| is offset of the first bit in dst[0] that will be modified. The 31 | // offset is from the MSB-side which means the first |bit_offset| MSBs in 32 | // |dst[0]| will not be modified. 33 | static inline void deparse_uint32(uint8_t *dst, uint8_t *src, 34 | int bit_offset, int width) { 35 | uint32_t tmp = htonl((ntohl(*(uint32_t *) src)) << (32 - width)); 36 | uint8_t *new_src = (uint8_t *) &tmp; 37 | int i; 38 | // First, zero-out the bits that we want to modify in |dst[0]|. 39 | uint8_t mask = (0xFF >> bit_offset); 40 | mask = ~mask; 41 | dst[0] = (dst[0] & mask); 42 | // Now, bitwise-or |8 - bit_offset| bits in |dst[0]| with |8 - bit_offset| 43 | // bits in |new_src[0]|. 44 | dst[0] |= (new_src[0] >> bit_offset); 45 | for (i = 1; i < BYTE_ROUND_UP(width); i++) { 46 | dst[i] = (new_src[i] >> bit_offset) | (new_src[i - 1] << (8 - bit_offset)); 47 | } 48 | /* Added this later, to fix bug */ 49 | /* if((bit_offset + width) > (i << 3)) */ 50 | // FIXME: We are changing bits in |dst[i]| beyond what is specified in 51 | // |width|. This will work fine as long as we call |deparse_uint32| in the 52 | // same sequence as fields appear in a packet. But, if we deparse fields in 53 | // arbitrary order, we will modify bits in the following field. 54 | if ((bit_offset + width) > (BYTE_ROUND_UP(width) << 3)) 55 | dst[i] = new_src[i - 1] << (8 - bit_offset); 56 | } 57 | 58 | static inline void deparse_byte_buf(uint8_t *dst, uint8_t *src, int len) { 59 | memcpy(dst, src, len); 60 | } 61 | 62 | //:: for header_instance in ordered_header_instances_non_virtual: 63 | void _deparse_${header_instance}(uint8_t *src, uint8_t *hdr); 64 | //:: #endfor 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_rpc_server.cpp: -------------------------------------------------------------------------------- 1 | //:: # Generate the handler routines for the interfaces 2 | 3 | //:: pd_prefix = "p4_pd_" + p4_prefix + "_" 4 | //:: pd_static_prefix = "p4_pd_" 5 | //:: api_prefix = p4_prefix + "_" 6 | 7 | #include 8 | #include 9 | #include "p4_sim/pd_rpc_server.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace ::apache::thrift; 17 | using namespace ::apache::thrift::protocol; 18 | using namespace ::apache::thrift::transport; 19 | using namespace ::apache::thrift::server; 20 | 21 | using boost::shared_ptr; 22 | 23 | #include "conn_mgr_pd_rpc_server.ipp" 24 | #include "mc_pd_rpc_server.ipp" 25 | #include "devport_mgr_pd_rpc_server.ipp" 26 | #include "p4_pd_rpc_server.ipp" 27 | 28 | /* 29 | * Thread wrapper for starting the server 30 | */ 31 | 32 | static void *rpc_server_thread(void *arg) { 33 | int port = *(int *) arg; 34 | 35 | shared_ptr<${p4_prefix}Handler> ${p4_prefix}_handler(new ${p4_prefix}Handler()); 36 | shared_ptr devport_mgr_handler(new devport_mgrHandler()); 37 | shared_ptr mc_handler(new mcHandler()); 38 | shared_ptr conn_mgr_handler(new conn_mgrHandler()); 39 | 40 | shared_ptr processor(new TMultiplexedProcessor()); 41 | processor->registerProcessor( 42 | "${p4_prefix}", 43 | shared_ptr(new ${p4_prefix}Processor(${p4_prefix}_handler)) 44 | ); 45 | processor->registerProcessor( 46 | "devport_mgr", 47 | shared_ptr(new devport_mgrProcessor(devport_mgr_handler)) 48 | ); 49 | processor->registerProcessor( 50 | "mc", 51 | shared_ptr(new mcProcessor(mc_handler)) 52 | ); 53 | processor->registerProcessor( 54 | "conn_mgr", 55 | shared_ptr(new conn_mgrProcessor(conn_mgr_handler)) 56 | ); 57 | shared_ptr serverTransport(new TServerSocket(port)); 58 | shared_ptr transportFactory(new TBufferedTransportFactory()); 59 | shared_ptr protocolFactory(new TBinaryProtocolFactory()); 60 | 61 | TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory); 62 | 63 | server.serve(); 64 | 65 | return NULL; 66 | } 67 | 68 | 69 | static pthread_t rpc_thread; 70 | 71 | int start_p4_pd_rpc_server(int port) 72 | { 73 | std::cerr << "\nP4 Program: ${p4_name}\n\n"; 74 | std::cerr << "Starting RPC server on port " << port << std::endl; 75 | 76 | int *port_arg = (int *) malloc(sizeof(int)); 77 | *port_arg = port; 78 | 79 | return pthread_create(&rpc_thread, NULL, rpc_server_thread, port_arg); 80 | } 81 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/mc_pd_rpc_server.ipp: -------------------------------------------------------------------------------- 1 | //:: pd_prefix = "p4_pd_" + p4_prefix + "_" 2 | //:: pd_static_prefix = "p4_pd_" 3 | //:: api_prefix = p4_prefix + "_" 4 | 5 | #include "mc.h" 6 | 7 | #include 8 | 9 | extern "C" { 10 | #include 11 | #include 12 | #include 13 | } 14 | 15 | using namespace ::mc_pd_rpc; 16 | using namespace ::res_pd_rpc; 17 | 18 | class mcHandler : virtual public mcIf { 19 | public: 20 | mcHandler() { 21 | 22 | } 23 | 24 | //:: if enable_pre: 25 | 26 | int32_t mc_init(){ 27 | return 0; 28 | } 29 | 30 | SessionHandle_t mc_create_session(){ 31 | SessionHandle_t sess_hdl; 32 | ::mc_create_session((uint32_t*)&sess_hdl); 33 | return sess_hdl; 34 | } 35 | 36 | int32_t mc_destroy_session(const SessionHandle_t sess_hdl){ 37 | return ::mc_destroy_session(sess_hdl); 38 | } 39 | 40 | int32_t mc_complete_operations(const SessionHandle_t sess_hdl){ 41 | return ::mc_complete_operations(sess_hdl); 42 | } 43 | 44 | McHandle_t mc_mgrp_create(const SessionHandle_t sess_hdl, const int dev, const int16_t mgid){ 45 | McHandle_t grp_hdl; 46 | ::mc_mgrp_create(sess_hdl, dev, mgid, (uint32_t*)&grp_hdl); 47 | return grp_hdl; 48 | } 49 | 50 | int32_t mc_mgrp_destroy(const SessionHandle_t sess_hdl, const int dev, const McHandle_t grp_hdl){ 51 | return ::mc_mgrp_destroy(sess_hdl, grp_hdl); 52 | } 53 | 54 | McHandle_t mc_node_create(const SessionHandle_t sess_hdl, const int dev, const int16_t rid, const std::string &port_map, const std::string &lag_map){ 55 | McHandle_t l1_hdl; 56 | ::mc_node_create(sess_hdl, dev, rid, (uint8_t*)port_map.c_str(), (uint8_t*)lag_map.c_str(), (uint32_t*)&l1_hdl); 57 | return l1_hdl; 58 | } 59 | 60 | McHandle_t mc_node_update(const SessionHandle_t sess_hdl, const int dev, const McHandle_t node_hdl, const std::string &port_map, const std::string &lag_map){ 61 | return ::mc_node_update(sess_hdl, node_hdl, (uint8_t*)port_map.c_str(), (uint8_t*)lag_map.c_str()); 62 | } 63 | 64 | int32_t mc_node_destroy(const SessionHandle_t sess_hdl, const int dev, const McHandle_t node_hdl){ 65 | return ::mc_node_destroy(sess_hdl, node_hdl); 66 | } 67 | 68 | int32_t mc_associate_node(const SessionHandle_t sess_hdl, const int dev, const McHandle_t grp_hdl, const McHandle_t l1_hdl){ 69 | return ::mc_associate_node(sess_hdl, grp_hdl, l1_hdl); 70 | } 71 | 72 | int32_t mc_dissociate_node(const SessionHandle_t sess_hdl, const int dev, const McHandle_t grp_hdl, const McHandle_t l1_hdl){ 73 | return ::mc_dissociate_node(sess_hdl, grp_hdl, l1_hdl); 74 | } 75 | 76 | int32_t mc_set_lag_membership(const SessionHandle_t sess_hdl, const int dev, const int8_t lag, const std::string &port_map){ 77 | int32_t y = ::mc_set_lag_membership(sess_hdl, dev, lag, (uint8_t*)port_map.c_str()); 78 | return y; 79 | } 80 | 81 | //:: #endif 82 | 83 | }; 84 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_static.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "rmt_internal.h" 20 | #include "stateful.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | static Pvoid_t used_session_handles; 27 | static pthread_mutex_t lock; 28 | 29 | p4_pd_status_t 30 | p4_pd_init(void) { 31 | pthread_mutex_init(&lock, NULL); 32 | used_session_handles = (Pvoid_t) NULL; 33 | return 0; 34 | } 35 | 36 | void 37 | p4_pd_cleanup(void) { 38 | Word_t Rc_word; 39 | J1FA(Rc_word, used_session_handles); 40 | } 41 | 42 | p4_pd_status_t 43 | p4_pd_client_init(p4_pd_sess_hdl_t *sess_hdl) { 44 | pthread_mutex_lock(&lock); 45 | 46 | int Rc_int; 47 | Word_t index = 0; 48 | J1FE(Rc_int, used_session_handles, index); 49 | *sess_hdl = (p4_pd_sess_hdl_t)index; 50 | 51 | J1S(Rc_int, used_session_handles, index); 52 | assert(1 == Rc_int); 53 | 54 | pthread_mutex_unlock(&lock); 55 | 56 | return 0; 57 | } 58 | 59 | p4_pd_status_t 60 | p4_pd_client_cleanup(p4_pd_sess_hdl_t sess_hdl) { 61 | pthread_mutex_lock(&lock); 62 | 63 | int Rc_int; 64 | J1U(Rc_int, used_session_handles, (Word_t)sess_hdl); 65 | if (0 == Rc_int) { 66 | RMT_LOG(P4_LOG_LEVEL_ERROR, "Cannot find session handle %u\n", (uint32_t)sess_hdl); 67 | } 68 | 69 | pthread_mutex_unlock(&lock); 70 | 71 | return (p4_pd_status_t)(1 == Rc_int ? 0 : 1); 72 | } 73 | 74 | p4_pd_status_t 75 | p4_pd_begin_txn(p4_pd_sess_hdl_t shdl, bool isAtomic, bool isHighPri) { 76 | return 0; 77 | } 78 | 79 | p4_pd_status_t 80 | p4_pd_verify_txn(p4_pd_sess_hdl_t shdl) { 81 | return 0; 82 | } 83 | 84 | p4_pd_status_t 85 | p4_pd_abort_txn(p4_pd_sess_hdl_t shdl) { 86 | return 0; 87 | } 88 | 89 | p4_pd_status_t 90 | p4_pd_commit_txn(p4_pd_sess_hdl_t shdl, bool hwSynchronous, bool *sendRsp) { 91 | return 0; 92 | } 93 | 94 | p4_pd_status_t 95 | p4_pd_complete_operations(p4_pd_sess_hdl_t shdl) { 96 | return 0; 97 | } 98 | 99 | uint16_t 100 | p4_pd_dev_port_to_pipe_id(uint16_t dev_port_id) 101 | { 102 | return ((dev_port_id >> 7) & 0x3); 103 | } 104 | 105 | int32_t 106 | p4_pd_set_meter_time(p4_pd_sess_hdl_t shdl, int32_t meter_time_disable) 107 | { 108 | return stateful_meter_set_meter_time(meter_time_disable); 109 | } 110 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/value_set.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "value_set.h" 20 | 21 | typedef tommy_list value_set_t; 22 | 23 | //:: for name, vs_info in value_sets.items(): 24 | typedef struct value_set_${name}_entry_s { 25 | //:: byte_width = vs_info["byte_width"] 26 | uint8_t value[${byte_width}]; 27 | uint8_t mask[${byte_width}]; 28 | tommy_node node; 29 | } value_set_${name}_entry_t; 30 | 31 | //:: #endfor 32 | 33 | //:: for name, vs_info in value_sets.items(): 34 | value_set_t value_set_${name}; 35 | //:: #endfor 36 | 37 | //:: for name, vs_info in value_sets.items(): 38 | //:: byte_width = vs_info["byte_width"] 39 | int value_set_${name}_contains(uint8_t *key) { 40 | tommy_node* node = tommy_list_head(&value_set_${name}); 41 | while (node) { 42 | value_set_${name}_entry_t * data = node->data; 43 | int result = cmp_values(key, data->value, ${byte_width}, data->mask); 44 | if(result) 45 | return 1; 46 | node = node->next; 47 | } 48 | return 0; 49 | } 50 | 51 | //:: #endfor 52 | 53 | //:: for name, vs_info in value_sets.items(): 54 | //:: byte_width = vs_info["byte_width"] 55 | void *value_set_${name}_add(uint8_t *value, uint8_t *mask) { 56 | value_set_${name}_entry_t *entry = malloc(sizeof(value_set_${name}_entry_t)); 57 | memcpy(entry->value, value, sizeof(entry->value)); 58 | memcpy(entry->mask, mask, sizeof(entry->mask)); 59 | tommy_list_insert_head(&value_set_${name}, &entry->node, entry); 60 | return &entry->node; 61 | } 62 | 63 | //:: #endfor 64 | 65 | //:: for name, vs_info in value_sets.items(): 66 | int value_set_${name}_delete(void *value) { 67 | void *entry = tommy_list_remove_existing(&value_set_${name}, value); 68 | if(!entry) 69 | return 1; 70 | free(entry); 71 | return 0; 72 | } 73 | 74 | //:: #endfor 75 | 76 | //:: for name, vs_info in value_sets.items(): 77 | //:: byte_width = vs_info["byte_width"] 78 | void *value_set_${name}_lookup(uint8_t *value, uint8_t *mask) { 79 | tommy_node* node = tommy_list_head(&value_set_${name}); 80 | while (node) { 81 | value_set_${name}_entry_t * data = node->data; 82 | if((!memcmp(data->value, value, sizeof(data->value))) && 83 | (!memcmp(data->mask, mask, sizeof(data->mask)))) 84 | return &data->node; 85 | node = node->next; 86 | } 87 | return NULL; 88 | } 89 | 90 | //:: #endfor 91 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/metadata_recirc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "enums.h" 21 | #include "fields.h" 22 | #include "metadata_recirc.h" 23 | 24 | struct metadata_recirc_set_s { 25 | bool fields_valid[RMT_FIELD_INSTANCE_COUNT]; 26 | int validity_count; 27 | }; 28 | 29 | metadata_recirc_set_t *metadata_recirc_create(void) { 30 | metadata_recirc_set_t * set = malloc(sizeof(metadata_recirc_set_t)); 31 | memset(set, 0, sizeof(metadata_recirc_set_t)); 32 | return set; 33 | } 34 | 35 | void metadata_recirc_add_field(metadata_recirc_set_t *set, 36 | rmt_field_instance_t field) { 37 | if(!set->fields_valid[field]) { 38 | set->fields_valid[field] = 1; 39 | set->validity_count++; 40 | } 41 | } 42 | 43 | void metadata_recirc_remove_field(metadata_recirc_set_t *set, 44 | rmt_field_instance_t field) { 45 | if(set->fields_valid[field]) { 46 | set->fields_valid[field] = 0; 47 | set->validity_count--; 48 | } 49 | } 50 | 51 | void metadata_recirc_add_header(metadata_recirc_set_t *set, 52 | rmt_header_instance_t hdr) { 53 | rmt_field_instance_t field = rmt_header_instance_first_field(hdr); 54 | int i; 55 | for (i = 0; i < rmt_header_instance_num_fields(hdr); i++) { 56 | if(!set->fields_valid[field + i]) { 57 | set->fields_valid[field + i] = 1; 58 | set->validity_count++; 59 | } 60 | } 61 | } 62 | 63 | int *metadata_recirc_digest(metadata_recirc_set_t *set) { 64 | int *res = malloc(sizeof(int) * (set->validity_count + 1)); 65 | res[0] = set->validity_count; 66 | int field; 67 | int pos = 1; 68 | for (field = 0; field < RMT_FIELD_INSTANCE_COUNT; field++) { 69 | if(set->fields_valid[field]) { 70 | res[pos++] = field; 71 | } 72 | } 73 | return res; 74 | } 75 | 76 | 77 | metadata_recirc_set_t *metadata_recirc_init(int *data) { 78 | metadata_recirc_set_t *set = metadata_recirc_create(); 79 | set->validity_count = data[0]; 80 | int i; 81 | for(i = 1; i < (data[0] + 1); i++) { 82 | set->fields_valid[data[i]] = 1; 83 | } 84 | return set; 85 | } 86 | 87 | void metadata_recirc_empty(metadata_recirc_set_t *set) { 88 | memset(set, 0, sizeof(metadata_recirc_set_t)); 89 | } 90 | 91 | int metadata_recirc_is_valid(metadata_recirc_set_t *set, 92 | rmt_field_instance_t field) { 93 | return set->fields_valid[field]; 94 | } 95 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pre.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PRE_H 18 | #define _RMT_PRE_H 19 | 20 | //:: if enable_pre: 21 | 22 | #include 23 | 24 | #define PRE_MGID_MAX 16384 25 | #define PRE_PORTS_MAX 256 26 | #define PRE_LAG_MAX 256 27 | #define PRE_L1_NODE_MAX 16384 28 | #define PRE_L2_NODE_MAX 4096 29 | 30 | typedef enum l1_node_type_ { 31 | L1_NODE_TYPE_RID = 1, 32 | L1_NODE_TYPE_RID_XID = 2, 33 | L1_NODE_TYPE_RID_NO_NEXT = 3, 34 | } l1_node_type_t; 35 | 36 | typedef uint16_t mgrp_id_t; 37 | typedef uint16_t mgrp_rid_t; 38 | typedef uint16_t mgrp_lag_id_t; 39 | typedef uint16_t mgrp_port_id_t; 40 | 41 | typedef uint32_t mc_mgrp_hdl_t; 42 | typedef uint32_t mc_node_hdl_t; 43 | 44 | p4_pd_status_t 45 | mc_create_session(p4_pd_sess_hdl_t *sess_hdl); 46 | 47 | p4_pd_status_t 48 | mc_destroy_session(p4_pd_sess_hdl_t sess_hdl); 49 | 50 | p4_pd_status_t 51 | mc_mgrp_create(p4_pd_sess_hdl_t session, 52 | int8_t device, 53 | mgrp_id_t mgid, 54 | mc_mgrp_hdl_t *mgrp_hdl); 55 | 56 | p4_pd_status_t 57 | mc_mgrp_destroy(p4_pd_sess_hdl_t session, 58 | mc_mgrp_hdl_t mgrp_hdl); 59 | 60 | p4_pd_status_t 61 | mc_node_create(p4_pd_sess_hdl_t session, 62 | int8_t device, 63 | mgrp_rid_t rid, 64 | const uint8_t *port_map, 65 | const uint8_t *lag_map, 66 | mc_node_hdl_t *node_hdl); 67 | 68 | p4_pd_status_t 69 | mc_node_destroy(p4_pd_sess_hdl_t session, 70 | mc_node_hdl_t node_hdl); 71 | 72 | p4_pd_status_t 73 | mc_node_update(p4_pd_sess_hdl_t session, 74 | mc_node_hdl_t node_hdl, 75 | const uint8_t *port_map, 76 | const uint8_t *lag_map); 77 | 78 | p4_pd_status_t 79 | mc_associate_node(p4_pd_sess_hdl_t session, 80 | mc_mgrp_hdl_t mgrp_hdl, 81 | mc_node_hdl_t node_hdl); 82 | 83 | p4_pd_status_t 84 | mc_dissociate_node(p4_pd_sess_hdl_t session, 85 | mc_mgrp_hdl_t mgrp_hdl, 86 | mc_node_hdl_t node_hdl); 87 | 88 | p4_pd_status_t 89 | mc_set_lag_membership(p4_pd_sess_hdl_t session, 90 | int8_t dev_id, 91 | mgrp_lag_id_t lag_id, 92 | const uint8_t *port_map); 93 | 94 | p4_pd_status_t 95 | mc_complete_operations(p4_pd_sess_hdl_t shdl); 96 | 97 | //:: #endif 98 | #endif /* _RMT_PRE_H */ 99 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pkt_manager.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "pkt_manager.h" 21 | #include "pipeline.h" 22 | #include "parser.h" 23 | #include "deparser.h" 24 | #include "queuing.h" 25 | #include "mirroring_internal.h" 26 | #include "rmt_internal.h" 27 | #include "enums.h" 28 | #include "lf.h" 29 | 30 | #include 31 | 32 | #define TRANSMIT_CB_SIZE 1024 33 | 34 | circular_buffer_t *rmt_transmit_cb; /* only 1 */ 35 | 36 | pthread_t pkt_out_thread; 37 | 38 | uint64_t packet_id; 39 | 40 | typedef struct transmit_pkt_s { 41 | buffered_pkt_t pkt; 42 | int egress; 43 | } transmit_pkt_t; 44 | 45 | int pkt_manager_receive(int ingress, void *pkt, int len) { 46 | void *pkt_data = malloc(len); 47 | memcpy(pkt_data, pkt, len); 48 | ++packet_id; 49 | ingress_pipeline_receive(ingress, NULL, NULL, 50 | pkt_data, len, packet_id, 51 | PKT_INSTANCE_TYPE_NORMAL); 52 | return 0; 53 | } 54 | 55 | int pkt_manager_transmit(int egress, void *pkt, int len, uint64_t packet_id) { 56 | transmit_pkt_t *t_pkt = malloc(sizeof(transmit_pkt_t)); 57 | buffered_pkt_t *b_pkt = &t_pkt->pkt; 58 | t_pkt->egress = egress; 59 | b_pkt->pkt_data = pkt; 60 | b_pkt->pkt_len = len; 61 | cb_write(rmt_transmit_cb, t_pkt); 62 | return 0; 63 | } 64 | 65 | static void *pkt_out_loop(void *arg) { 66 | while(1) { 67 | transmit_pkt_t *t_pkt = (transmit_pkt_t *) cb_read(rmt_transmit_cb); 68 | buffered_pkt_t *b_pkt = &t_pkt->pkt; 69 | RMT_LOG(P4_LOG_LEVEL_TRACE, "outgoing thread: packet dequeued\n"); 70 | if(rmt_instance->tx_fn) { 71 | RMT_LOG(P4_LOG_LEVEL_VERBOSE, 72 | "outgoing thread: sending pkt: Size[%u]: Port[%d]\n", b_pkt->pkt_len, 73 | t_pkt->egress); 74 | rmt_instance->tx_fn(t_pkt->egress, b_pkt->pkt_data, b_pkt->pkt_len); 75 | } 76 | free(b_pkt->pkt_data); 77 | free(t_pkt); 78 | } 79 | return NULL; 80 | } 81 | 82 | void pkt_manager_init(void) { 83 | rmt_transmit_cb = cb_init(TRANSMIT_CB_SIZE, CB_WRITE_BLOCK, CB_READ_BLOCK); 84 | 85 | packet_id = 0; 86 | 87 | lf_init(); 88 | 89 | ingress_pipeline_init(); 90 | 91 | queuing_init(); 92 | 93 | mirroring_init(); 94 | 95 | egress_pipeline_init(); 96 | 97 | pthread_create(&pkt_out_thread, NULL, 98 | pkt_out_loop, NULL); 99 | } 100 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pd_pre.h: -------------------------------------------------------------------------------- 1 | #ifndef _RMT_PD_PRE_H 2 | #define _RMT_PD_PRE_H 3 | 4 | //:: if enable_pre: 5 | 6 | #include 7 | 8 | /* Multicast session APIs. */ 9 | p4_pd_status_t 10 | p4_pd_mc_create_session(p4_pd_sess_hdl_t *sess_hdl); 11 | 12 | p4_pd_status_t 13 | p4_pd_mc_destroy_session(p4_pd_sess_hdl_t sess_hdl); 14 | 15 | p4_pd_status_t 16 | p4_pd_mc_complete_operations(p4_pd_sess_hdl_t sess_hdl); 17 | 18 | /* Multicast group APIs. */ 19 | p4_pd_status_t 20 | p4_pd_mc_mgrp_create(p4_pd_sess_hdl_t sess_hdl, int dev, uint16_t grp, 21 | p4_pd_entry_hdl_t *grp_hdl); 22 | p4_pd_status_t 23 | p4_pd_mc_mgrp_destroy(p4_pd_sess_hdl_t sess_hdl, int dev, 24 | p4_pd_entry_hdl_t grp_hdl); 25 | 26 | /* Multicast ECMP APIs. */ 27 | p4_pd_status_t 28 | p4_pd_mc_ecmp_create(p4_pd_sess_hdl_t sess_hdl, int dev, 29 | p4_pd_entry_hdl_t *ecmp_hdl); 30 | 31 | p4_pd_status_t 32 | p4_pd_mc_ecmp_destroy(p4_pd_sess_hdl_t sess_hdl, int dev, 33 | p4_pd_entry_hdl_t ecmp_hdl); 34 | 35 | p4_pd_status_t 36 | p4_pd_mc_ecmp_mbr_add(p4_pd_sess_hdl_t sess_hdl, int dev, 37 | p4_pd_entry_hdl_t ecmp_hdl, 38 | p4_pd_entry_hdl_t l1_hdl); 39 | 40 | p4_pd_status_t 41 | p4_pd_mc_ecmp_mbr_rem(p4_pd_sess_hdl_t sess_hdl, int dev, 42 | p4_pd_entry_hdl_t ecmp_hdl, 43 | p4_pd_entry_hdl_t l1_hdl); 44 | 45 | p4_pd_status_t 46 | p4_pd_mc_associate_ecmp(p4_pd_sess_hdl_t sess_hdl, int dev, 47 | p4_pd_entry_hdl_t grp_hdl, 48 | p4_pd_entry_hdl_t ecmp_hdl, 49 | uint16_t xid, bool xid_valid); 50 | 51 | p4_pd_status_t 52 | p4_pd_mc_dissociate_ecmp(p4_pd_sess_hdl_t sess_hdl, int dev, 53 | p4_pd_entry_hdl_t grp_hdl, 54 | p4_pd_entry_hdl_t ecmp_hdl); 55 | 56 | p4_pd_status_t 57 | p4_pd_mc_node_create(p4_pd_sess_hdl_t sess_hdl, int dev, uint16_t rid, 58 | uint8_t *port_map, uint8_t *lag_map, 59 | p4_pd_entry_hdl_t *node_hdl); 60 | 61 | p4_pd_status_t 62 | p4_pd_mc_node_update(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t node_hdl, 63 | uint8_t *port_map, uint8_t *lag_map); 64 | 65 | p4_pd_status_t 66 | p4_pd_mc_node_destroy(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t node_hdl); 67 | 68 | p4_pd_status_t 69 | p4_pd_mc_associate_node(p4_pd_sess_hdl_t sess_hdl, int dev, 70 | p4_pd_entry_hdl_t grp_hdl, 71 | p4_pd_entry_hdl_t l1_hdl, 72 | uint16_t xid, bool xid_valid); 73 | 74 | p4_pd_status_t 75 | p4_pd_mc_dissociate_node(p4_pd_sess_hdl_t sess_hdl, int dev, 76 | p4_pd_entry_hdl_t grp_hdl, 77 | p4_pd_entry_hdl_t node_hdl); 78 | 79 | p4_pd_status_t 80 | p4_pd_mc_set_lag_membership(p4_pd_sess_hdl_t sess_hdl, int dev, uint8_t lag, 81 | uint8_t *port_map); 82 | //:: #endif 83 | #endif /* _RMT_PD_PRE_H */ 84 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/stateful.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_STATEFUL_H 18 | #define _RMT_STATEFUL_H 19 | 20 | #include 21 | #include "enums.h" 22 | #include "phv.h" 23 | 24 | typedef enum meter_color_e { 25 | METER_EXCEED_ACTION_COLOR_GREEN = 0, 26 | METER_EXCEED_ACTION_COLOR_YELLOW, 27 | METER_EXCEED_ACTION_COLOR_RED, 28 | METER_EXCEED_ACTION_COLOR_END_, 29 | } meter_color_t; 30 | 31 | typedef struct meter_s meter_t; 32 | typedef struct counter_s counter_t; 33 | typedef struct reg_s reg_t; 34 | 35 | /* TODO: make something more like field lists ? */ 36 | 37 | //:: for c_name, c_info in counter_info.items(): 38 | //:: type_ = c_info["type_"] 39 | //:: if type_ == "packets_and_bytes": continue 40 | extern counter_t counter_${c_name}; 41 | //:: #endfor 42 | 43 | //:: for m_name, m_info in meter_info.items(): 44 | extern meter_t meter_${m_name}; 45 | //:: #endfor 46 | 47 | //:: for r_name, r_info in register_info.items(): 48 | extern reg_t reg_${r_name}; 49 | //:: #endfor 50 | 51 | void stateful_init(void); 52 | 53 | void stateful_init_counters(counter_t *counter, size_t num_instances, char *name); 54 | uint64_t stateful_read_counter(counter_t *counter, int index); 55 | void stateful_write_counter(counter_t *counter, int index, uint64_t value); 56 | void stateful_increase_counter(counter_t *counter, int index, uint64_t value); 57 | void stateful_reset_counter(counter_t *counter, int index); 58 | void stateful_clean_all(void); 59 | 60 | void stateful_init_meters(meter_t *meter, size_t num_instances, char *name); 61 | void stateful_reset_meter(meter_t *meter, int index); 62 | int stateful_meter_set_queue(meter_t *meter, int index, 63 | double info_rate, uint32_t burst_size, 64 | meter_color_t color); 65 | meter_color_t stateful_execute_meter(meter_t *meter, int index, uint32_t input); 66 | int32_t stateful_meter_set_meter_time(int32_t meter_time_disable); 67 | 68 | void stateful_init_registers(reg_t *reg, size_t num_instances, size_t byte_width); 69 | 70 | //:: for r_name, r_info in register_info.items(): 71 | //:: byte_width = r_info["byte_width"] 72 | void stateful_write_register_${r_name}(int index, uint8_t *src, int src_len); 73 | //:: #endfor 74 | 75 | //:: for r_name, r_info in register_info.items(): 76 | //:: byte_width = r_info["byte_width"] 77 | void stateful_read_register_${r_name}(phv_data_t *phv, int index, 78 | rmt_field_instance_t dst, int dst_len, 79 | uint8_t *mask_ptr, int mask_len); 80 | //:: #endfor 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /p4c_bm/util/topo_sorting.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class Node(object): 16 | def __init__(self, n): 17 | self.n = n 18 | self.edges = set() 19 | 20 | def add_edge_to(self, other): 21 | assert(isinstance(other, Node)) 22 | self.edges.add(other) 23 | 24 | def __str__(self): 25 | return self.n.name 26 | 27 | def print_(self): 28 | print "node", self, "edges:", ", ".join([str(n) for n in self.edges]) 29 | for n in self.edges: 30 | n.print_() 31 | 32 | class Graph(object): 33 | def __init__(self): 34 | self.nodes = {} 35 | self.root = None 36 | 37 | def add_node(self, node): 38 | assert(node not in self.nodes) 39 | self.nodes[node] = Node(node) 40 | 41 | def __contains__(self, node): 42 | return node in self.nodes 43 | 44 | def get_node(self, node): 45 | return self.nodes[node] 46 | 47 | def produce_topo_sorting(self): 48 | def visit(node, topo_sorting, sequence = None): 49 | if sequence is not None: sequence += [str(node)] 50 | if node._behavioral_topo_sorting_mark == 1: 51 | if sequence is not None: print "cycle", sequence 52 | return False 53 | if node._behavioral_topo_sorting_mark != 2: 54 | node._behavioral_topo_sorting_mark = 1 55 | for next_node in node.edges: 56 | if sequence is not None: 57 | res = visit(next_node, topo_sorting, list(sequence)) 58 | else: 59 | res = visit(next_node, topo_sorting) 60 | if not res: return False 61 | node._behavioral_topo_sorting_mark = 2 62 | topo_sorting.insert(0, node.n) 63 | return True 64 | 65 | 66 | has_cycle = False 67 | topo_sorting = [] 68 | 69 | for node in self.nodes.values(): 70 | # 0 is unmarked, 1 is temp, 2 is permanent 71 | node._behavioral_topo_sorting_mark = 0 72 | for node in self.nodes.values(): 73 | if node._behavioral_topo_sorting_mark == 0: 74 | if not visit(node, topo_sorting, sequence = []): 75 | has_cycle = True 76 | break 77 | # removing mark 78 | for node in self.nodes.values(): 79 | del node._behavioral_topo_sorting_mark 80 | 81 | assert(not has_cycle) 82 | 83 | return topo_sorting 84 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/conditional_tables.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "phv.h" 18 | #include "tables.h" 19 | #include "fields.h" 20 | 21 | #include 22 | 23 | //:: for conditional, ct_info in conditional_table_info.items(): 24 | /* ${ct_info["expression"]} */ 25 | void tables_apply_${conditional}(phv_data_t *phv) { 26 | /* First, compute the expression to branch on */ 27 | //:: num_registers = len(ct_info["expression_computation"]) 28 | /* 29 | We are assuming that each instruction uses 1 register and numbering starts 30 | with 0. 31 | */ 32 | uint32_t reg[${num_registers}]; 33 | 34 | //:: for instruction in ct_info["expression_computation"]: 35 | //:: dest_reg, operation, v1 = instruction[:3] 36 | //:: if len(instruction) > 3: v2 = instruction[3] 37 | //:: if operation == "assign_immediate": 38 | ${dest_reg} = (uint32_t) ${v1}; 39 | //:: elif operation == "assign_field": 40 | ${dest_reg} = phv_buf_field_uint32_get(phv, rmt_field_byte_offset_phv(RMT_FIELD_INSTANCE_${v1})); 41 | ${dest_reg} = ntohl(${dest_reg}); 42 | //:: elif operation == "not": 43 | ${dest_reg} = !${v1}; 44 | //:: elif operation == "or": 45 | ${dest_reg} = ${v1} || ${v2}; 46 | //:: elif operation == "and": 47 | ${dest_reg} = ${v1} && ${v2}; 48 | //:: elif operation == "==": 49 | ${dest_reg} = ${v1} == ${v2}; 50 | //:: elif operation == "!=": 51 | ${dest_reg} = ${v1} != ${v2}; 52 | //:: elif operation == ">": 53 | ${dest_reg} = ${v1} > ${v2}; 54 | //:: elif operation == ">=": 55 | ${dest_reg} = ${v1} >= ${v2}; 56 | //:: elif operation == "<": 57 | ${dest_reg} = ${v1} < ${v2}; 58 | //:: elif operation == "<=": 59 | ${dest_reg} = ${v1} <= ${v2}; 60 | //:: elif operation == "valid_header": 61 | ${dest_reg} = phv_is_valid_header(phv, RMT_HEADER_INSTANCE_${v1}); 62 | //:: elif operation == "valid_field": 63 | ${dest_reg} = phv_is_valid_field(phv, RMT_FIELD_INSTANCE_${v1}); 64 | //:: elif operation == "&": 65 | ${dest_reg} = (${v1} & ${v2}); 66 | //:: else: 67 | //:: assert(False) 68 | //:: #endif 69 | //:: #endfor 70 | 71 | /* Now jump to the next table based on the result */ 72 | //:: next_true = ct_info["next_tables"][True] 73 | //:: next_false = ct_info["next_tables"][False] 74 | if(reg[0]) { 75 | //:: if next_true is not None: 76 | tables_apply_${next_true}(phv); 77 | //:: #endif 78 | return; 79 | } 80 | else { 81 | //:: if next_false is not None: 82 | tables_apply_${next_false}(phv); 83 | //:: #endif 84 | return; 85 | } 86 | } 87 | 88 | //:: #endfor 89 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pg.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PG_H 18 | #define _RMT_PG_H 19 | #include "pd_static.h" 20 | 21 | typedef enum pd_p4_pktgen_trigger_type { 22 | PD_PKTGEN_TRIGGER_TIMER_ONE_SHOT=0, 23 | PD_PKTGEN_TRIGGER_TIMER_PERIODIC=1, 24 | PD_PKTGEN_TRIGGER_PORT_DOWN=2, 25 | PD_PKTGEN_TRIGGER_RECIRC_PATTERN=3 26 | } p4_pd_pktgen_trigger_type_e; 27 | 28 | typedef struct p4_pd_pktgen_app_cfg { 29 | p4_pd_pktgen_trigger_type_e trigger_type; 30 | uint16_t batch_count; 31 | uint16_t packets_per_batch; 32 | uint32_t pattern_value; 33 | uint32_t pattern_mask; 34 | uint32_t timer_nanosec; 35 | uint32_t ibg; 36 | uint32_t ibg_jitter; 37 | uint32_t ipg; 38 | uint32_t ipg_jitter; 39 | uint16_t source_port; 40 | bool increment_source_port; 41 | uint16_t pkt_buffer_offset; 42 | uint16_t length; 43 | } p4_pd_pktgen_app_cfg; 44 | 45 | enum { 46 | PKTGEN_SUCCESS = 0, 47 | PKTGEN_CONFIG_ERR 48 | }; 49 | 50 | p4_pd_status_t 51 | p4_pd_recirculation_enable(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 52 | 53 | p4_pd_status_t 54 | p4_pd_recirculation_disable(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 55 | 56 | p4_pd_status_t 57 | p4_pd_pktgen_enable(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 58 | 59 | p4_pd_status_t 60 | p4_pd_pktgen_disable(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 61 | 62 | p4_pd_status_t 63 | p4_pd_pktgen_enable_recirc_pattern_matching(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 64 | 65 | p4_pd_status_t 66 | p4_pd_pktgen_disable_recirc_pattern_matching(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 67 | 68 | p4_pd_status_t 69 | p4_pd_pktgen_clear_port_down(p4_pd_sess_hdl_t shdl, uint32_t dev, uint32_t port); 70 | 71 | p4_pd_status_t 72 | p4_pd_pktgen_cfg_app(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id, p4_pd_pktgen_app_cfg* cfg); 73 | 74 | p4_pd_status_t 75 | p4_pd_pktgen_app_enable(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id); 76 | 77 | p4_pd_status_t 78 | p4_pd_pktgen_app_disable(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id); 79 | 80 | p4_pd_status_t 81 | p4_pd_pktgen_write_pkt_buffer(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t offset, uint32_t size, uint8_t* buf); 82 | 83 | p4_pd_stat_t 84 | p4_pd_pktgen_get_batch_counter(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id); 85 | 86 | p4_pd_stat_t 87 | p4_pd_pktgen_get_pkt_counter(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id); 88 | 89 | p4_pd_stat_t 90 | p4_pd_pktgen_get_trigger_counter(p4_pd_sess_hdl_t shdl, p4_pd_dev_target_t dev, uint32_t app_id); 91 | 92 | #endif /* _RMT_PG_H */ 93 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/rmt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file 19 | * 20 | * @brief Header file for high level interfaces to simulation core 21 | * 22 | */ 23 | 24 | #ifndef _RMT_RMT_H 25 | #define _RMT_RMT_H 26 | 27 | /* PLACEHOLDER */ 28 | typedef int p4_port_t; 29 | 30 | /** 31 | * @brief Initialize the forwarding simulation 32 | */ 33 | 34 | extern void rmt_init(void); 35 | 36 | /** 37 | * @brief Send a packet in for processing 38 | * 39 | * @param ingress The ingress port on which the packet was received 40 | * @param pkt Pointer to the packet data 41 | * @param len The number of bytes in the packet 42 | * 43 | * @return_val 0 Success 44 | * @return_val -1 Error 45 | */ 46 | 47 | extern int rmt_process_pkt(p4_port_t ingress, void *pkt, int len); 48 | 49 | /** 50 | * @brief Function pointer for packet transmit vector 51 | */ 52 | 53 | typedef void (*rmt_transmit_vector_f)(p4_port_t egress, void *pkt, int len); 54 | 55 | /** 56 | * @brief Register the transmit function with the forwarding simulation 57 | * 58 | * @param tx_fn The transmit function to use (or NULL to deregister) 59 | */ 60 | 61 | extern void rmt_transmit_register(rmt_transmit_vector_f tx_fn); 62 | 63 | /** 64 | * @brief Typedef of logging vector 65 | * 66 | * Just looks like printf 67 | */ 68 | 69 | typedef int (*p4_logging_f)(char *format, ...); 70 | 71 | /** 72 | * @brief Set the logging vector 73 | * 74 | * @param log_fn The logging vector; set to NULL to disable logging 75 | */ 76 | 77 | extern void rmt_logger_set(p4_logging_f log_fn); 78 | 79 | /** 80 | * @brief Enumeration of logging levels understood by sim 81 | * 82 | * Simple linear levels 83 | */ 84 | typedef enum p4_log_level_e { 85 | P4_LOG_LEVEL_NONE, /** No output */ 86 | P4_LOG_LEVEL_FATAL, /** Only fatal errors */ 87 | P4_LOG_LEVEL_ERROR, /** Errors */ 88 | P4_LOG_LEVEL_WARN, /** Warnings */ 89 | P4_LOG_LEVEL_INFO, /** Informational */ 90 | P4_LOG_LEVEL_VERBOSE, /** Verbose */ 91 | P4_LOG_LEVEL_TRACE, /** Most fn calls */ 92 | } p4_log_level_t; 93 | 94 | /** 95 | * @brief Set the log level for the forwarding code 96 | * 97 | * @param level The log level 98 | */ 99 | extern void rmt_log_level_set(p4_log_level_t level); 100 | 101 | /** 102 | * @brief Get the current log level 103 | */ 104 | extern p4_log_level_t rmt_log_level_get(void); 105 | 106 | 107 | /* 108 | * Other APIs we expect to need for the simulation 109 | * 110 | * Set up the multicast tables 111 | * Queue configuration 112 | */ 113 | 114 | extern void rmt_cleanup(void); 115 | extern int set_packets_per_sec(const int pps); 116 | extern int set_drop_tail_thr(const int thr); 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/mirroring.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_MIRRORING_H 18 | #define _RMT_MIRRORING_H 19 | 20 | #include 21 | #include "pd_static.h" 22 | 23 | //:: pd_prefix = "p4_pd_" + p4_prefix + "_" 24 | 25 | /* returns 0 if success */ 26 | int p4_pd_mirroring_mapping_add(p4_pd_mirror_id_t mirror_id, 27 | uint16_t egress_port 28 | ); 29 | /* returns 0 if success */ 30 | int p4_pd_mirror_session_create(p4_pd_sess_hdl_t shdl, 31 | p4_pd_dev_target_t dev_tgt, 32 | p4_pd_mirror_type_e type, 33 | p4_pd_direction_t dir, 34 | p4_pd_mirror_id_t id, 35 | uint16_t egr_port, 36 | uint16_t max_pkt_len, 37 | uint8_t cos, 38 | bool c2c, 39 | uint16_t extract_len, 40 | uint32_t timeout_usec, 41 | uint32_t *int_hdr, 42 | uint8_t int_hdr_len 43 | ); 44 | /* returns 0 if success */ 45 | int p4_pd_mirror_session_update(p4_pd_sess_hdl_t shdl, 46 | p4_pd_dev_target_t dev_tgt, 47 | p4_pd_mirror_type_e type, 48 | p4_pd_direction_t dir, 49 | p4_pd_mirror_id_t id, 50 | uint16_t egr_port, 51 | uint16_t max_pkt_len, 52 | uint8_t cos, 53 | bool c2c, 54 | uint16_t extract_len, 55 | uint32_t timeout_usec, 56 | uint32_t *int_hdr, 57 | uint8_t int_hdr_len, 58 | bool enable 59 | ); 60 | /* returns 0 if success */ 61 | int p4_pd_mirroring_mapping_delete(p4_pd_mirror_id_t mirror_id); 62 | /* returns 0 if success */ 63 | int p4_pd_mirror_session_delete(p4_pd_sess_hdl_t shdl, 64 | p4_pd_dev_target_t dev_tgt, 65 | p4_pd_mirror_id_t mirror_id); 66 | 67 | int p4_pd_mirroring_mapping_get_egress_port(int mirror_id); 68 | 69 | int p4_pd_mirroring_add_coalescing_session(const int mirror_id, const int egress_port, const int8_t *header, const int8_t header_length, const int16_t min_pkt_size, const int8_t timeout); 70 | int p4_pd_mirroring_set_coalescing_sessions_offset(const uint16_t offset); 71 | #endif 72 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/portmanager.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "portmanager.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "rmt_internal.h" 27 | 28 | pthread_t port_monitor_th; 29 | extern bmi_port_mgr_t* g_port_mgr; 30 | tommy_list port_list; 31 | 32 | 33 | struct functor_node { 34 | tommy_node node; 35 | port_fn func; 36 | }; 37 | 38 | typedef struct port_status { 39 | bool status; 40 | bool added; 41 | }port_status; 42 | 43 | port_status* status_w = NULL; 44 | 45 | p4_pd_status_t p4_port_add(uint32_t port_id) { 46 | if (!status_w || status_w[port_id].added) return P4_PD_FAILURE; 47 | RMT_LOG(P4_LOG_LEVEL_TRACE, "Adding port: %u\n", port_id); 48 | status_w[port_id].added = true; 49 | return P4_PD_SUCCESS; 50 | 51 | } 52 | p4_pd_status_t p4_port_remove(uint32_t port_id) { 53 | if (!status_w || !status_w[port_id].added) return P4_PD_FAILURE; 54 | RMT_LOG(P4_LOG_LEVEL_TRACE, "Removing port: %u\n", port_id); 55 | status_w[port_id].added = false; 56 | return P4_PD_SUCCESS; 57 | 58 | } 59 | 60 | 61 | bool port_is_up(int port) { 62 | bool is_up = false; 63 | if (0 >= port || PORT_COUNT_MAX < port) return false; 64 | if (g_port_mgr == NULL) return false; 65 | if (bmi_port_interface_is_up(g_port_mgr, port, &is_up)) return false; 66 | return is_up; 67 | 68 | } 69 | 70 | void port_handler(int port, bool status) { 71 | tommy_node* i = tommy_list_head(&port_list); 72 | while (i) { 73 | struct functor_node* f_node = i->data; 74 | f_node->func(port, status); 75 | i = i->next; 76 | } 77 | } 78 | 79 | void* port_monitor(void* arg) { 80 | int i = 0; 81 | status_w = (port_status *)calloc(PORT_COUNT_MAX, sizeof(port_status)); 82 | assert(status_w); 83 | while (1) { 84 | usleep(100); 85 | for (i = 0; i < PORT_COUNT_MAX; i ++) { 86 | bool x = port_is_up(i); 87 | if (!x && status_w[i].status) { 88 | port_handler(i, false); 89 | } 90 | if (x && !status_w[i].status) { 91 | port_handler(i, true); 92 | } 93 | status_w[i].status = x; 94 | } 95 | } 96 | free(status_w); 97 | status_w = NULL; 98 | 99 | 100 | } 101 | 102 | 103 | /* 104 | * Limited to detecting whenever port up/down events happen 105 | */ 106 | 107 | void portmgr_init(void) { 108 | if (g_port_mgr == NULL) return; 109 | tommy_list_init(&port_list); 110 | pthread_create(&port_monitor_th, NULL, port_monitor, NULL); 111 | } 112 | 113 | void portmgr_register_cb(port_fn func) { 114 | struct functor_node* f_node = (struct functor_node *)malloc(sizeof(struct functor_node)); 115 | f_node->func = func; 116 | tommy_list_insert_tail(&port_list, &f_node->node, f_node); 117 | } 118 | 119 | 120 | void portmgr_cleanup(void) { 121 | pthread_cancel(port_monitor_th); 122 | pthread_join(port_monitor_th, NULL); 123 | tommy_list_foreach(&port_list, free); 124 | } 125 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/phv.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "phv.h" 18 | #include "stdlib.h" 19 | 20 | phv_data_t *phv_init(int phv_id, int pipeline_type) { 21 | phv_data_t *phv = malloc(sizeof(phv_data_t)); 22 | phv->id = phv_id; 23 | phv->headers = malloc(PHV_LENGTH); 24 | phv->metadata_resubmit = metadata_recirc_create(); 25 | phv->metadata_recirc = metadata_recirc_create(); 26 | phv->pipeline_type = pipeline_type; 27 | //:: num_virtual_fields = len(ordered_field_instances_virtual) 28 | phv->field_virtual_instances = calloc(${num_virtual_fields + 1}, 29 | sizeof(rmt_field_instance_t)); 30 | //:: num_virtual_headers = len(ordered_header_instances_virtual) 31 | phv->header_virtual_instances = calloc(${num_virtual_headers + 1}, 32 | sizeof(rmt_header_instance_t)); 33 | return phv; 34 | } 35 | 36 | /* Data for metadata initialization */ 37 | uint8_t metadata_initializer[] = { 38 | //:: for header in ordered_header_instances_metadata: 39 | //:: h_info = header_info[header] 40 | //:: for field in h_info["fields"]: 41 | //:: f_info = field_info[field] 42 | /* ${field} */ 43 | //:: bytes = [str(b) + ", " for b in f_info["default"]] 44 | ${''.join(bytes)} 45 | //:: #endfor 46 | //:: #endfor 47 | }; 48 | 49 | //:: num_virtual_fields = len(ordered_field_instances_virtual) 50 | //:: num_virtual_headers = len(ordered_header_instances_virtual) 51 | static void reset_virtual_instances(phv_data_t *phv) { 52 | /* this takes care of the "last" instances, which need to be set to 53 | RMT_*_INSTANCE_NONE, i.e. 0 */ 54 | memset(phv->header_virtual_instances, 0, 55 | ${num_virtual_headers} * sizeof(rmt_header_instance_t)); 56 | memset(phv->field_virtual_instances, 0, 57 | ${num_virtual_fields} * sizeof(rmt_field_instance_t)); 58 | //:: for header_instance in ordered_header_instances_virtual: 59 | //:: h_info = header_info[header_instance] 60 | //:: if h_info["virtual_type"] == "next": 61 | //:: first_tag = tag_stacks_first[h_info["base_name"]] 62 | phv->header_virtual_instances[RMT_HEADER_INSTANCE_${header_instance}] =\ 63 | RMT_HEADER_INSTANCE_${first_tag}; 64 | //:: for i in xrange(len(h_info["fields"])): 65 | //:: first_tag_field = header_info[first_tag]["fields"][i] 66 | phv->field_virtual_instances[RMT_FIELD_INSTANCE_${h_info["fields"][i]}] =\ 67 | RMT_FIELD_INSTANCE_${first_tag_field}; 68 | //:: #endfor 69 | //:: #endif 70 | 71 | //:: #endfor 72 | } 73 | 74 | void phv_clean(phv_data_t *phv) { 75 | memset(phv->headers + PHV_HEADER_START, 0, PHV_HEADER_LENGTH); 76 | /* TODO: replace by metadata initializer */ 77 | /* memset(phv->headers + PHV_METADATA_START, 0, PHV_METADATA_LENGTH); */ 78 | memcpy(phv->headers + PHV_METADATA_START, 79 | metadata_initializer, PHV_METADATA_LENGTH); 80 | memset(phv->headers_valid, 0, sizeof(phv->headers_valid)); 81 | phv->resubmit_signal = 0; 82 | metadata_recirc_empty(phv->metadata_resubmit); 83 | phv->deparser_drop_signal = 0; 84 | phv->truncated_length = 0; 85 | metadata_recirc_empty(phv->metadata_recirc); 86 | reset_virtual_instances(phv); 87 | //:: for header in meta_carry: 88 | metadata_recirc_add_header(phv->metadata_recirc, 89 | RMT_HEADER_INSTANCE_${header}); 90 | //:: #endfor 91 | } 92 | -------------------------------------------------------------------------------- /p4c_bm/templates/inc/pd_static.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PD_STATIC_H 18 | #define _RMT_PD_STATIC_H 19 | 20 | #include 21 | #include 22 | 23 | enum { 24 | P4_PD_SUCCESS = 0, 25 | P4_PD_FAILURE = 20 26 | }; 27 | 28 | typedef uint32_t p4_pd_status_t; 29 | 30 | typedef uint32_t p4_pd_sess_hdl_t; 31 | 32 | typedef uint32_t p4_pd_entry_hdl_t; 33 | typedef uint32_t p4_pd_mbr_hdl_t; 34 | typedef uint32_t p4_pd_grp_hdl_t; 35 | typedef uint64_t p4_pd_stat_t; 36 | 37 | /* TODO: change that, it is horrible */ 38 | typedef void* p4_pd_value_hdl_t; 39 | 40 | #define PD_DEV_PIPE_ALL 0xffff 41 | typedef struct p4_pd_dev_target { 42 | int device_id; /*!< Device Identifier the API request is for */ 43 | uint16_t dev_pipe_id;/*!< If specified localizes target to the resources 44 | * only accessible to the port. DEV_PIPE_ALL serves 45 | * as a wild-card value 46 | */ 47 | } p4_pd_dev_target_t; 48 | 49 | typedef struct p4_pd_counter_value { 50 | uint64_t packets; 51 | uint64_t bytes; 52 | } p4_pd_counter_value_t; 53 | 54 | p4_pd_status_t 55 | p4_pd_init(void); 56 | 57 | void 58 | p4_pd_cleanup(void); 59 | 60 | p4_pd_status_t 61 | p4_pd_client_init(p4_pd_sess_hdl_t *sess_hdl); 62 | 63 | p4_pd_status_t 64 | p4_pd_client_cleanup(p4_pd_sess_hdl_t sess_hdl); 65 | 66 | p4_pd_status_t 67 | p4_pd_begin_txn(p4_pd_sess_hdl_t shdl, bool isAtomic, bool isHighPri); 68 | 69 | p4_pd_status_t 70 | p4_pd_verify_txn(p4_pd_sess_hdl_t shdl); 71 | 72 | p4_pd_status_t 73 | p4_pd_abort_txn(p4_pd_sess_hdl_t shdl); 74 | 75 | p4_pd_status_t 76 | p4_pd_commit_txn(p4_pd_sess_hdl_t shdl, bool hwSynchronous, bool *sendRsp); 77 | 78 | p4_pd_status_t 79 | p4_pd_complete_operations(p4_pd_sess_hdl_t shdl); 80 | 81 | int32_t p4_pd_set_meter_time(p4_pd_sess_hdl_t shdl, 82 | int32_t meter_time_disable); 83 | uint16_t 84 | p4_pd_dev_port_to_pipe_id(uint16_t dev_port_id); 85 | 86 | typedef void (*p4_pd_stat_ent_sync_cb) (int device_id, void *cookie); 87 | typedef void (*p4_pd_stat_sync_cb) (int device_id, void *cookie); 88 | 89 | #define COUNTER_READ_HW_SYNC (1 << 0) 90 | 91 | /* mirroring definitions */ 92 | typedef enum { 93 | PD_MIRROR_TYPE_NORM = 0, 94 | PD_MIRROR_TYPE_COAL, 95 | PD_MIRROR_TYPE_MAX 96 | } p4_pd_mirror_type_e; 97 | 98 | typedef enum { 99 | PD_DIR_NONE = 0, 100 | PD_DIR_INGRESS, 101 | PD_DIR_EGRESS, 102 | PD_DIR_BOTH 103 | } p4_pd_direction_t; 104 | 105 | typedef enum { 106 | PD_METER_TYPE_COLOR_AWARE, /* Color aware meter */ 107 | PD_METER_TYPE_COLOR_UNAWARE, /* Color unaware meter */ 108 | } p4_pd_meter_type_t; 109 | 110 | typedef enum { 111 | PD_INGRESS_POOL_0, 112 | PD_INGRESS_POOL_1, 113 | PD_INGRESS_POOL_2, 114 | PD_INGRESS_POOL_3, 115 | PD_EGRESS_POOL_0, 116 | PD_EGRESS_POOL_1, 117 | PD_EGRESS_POOL_2, 118 | PD_EGRESS_POOL_3, 119 | } p4_pd_pool_id_t; 120 | 121 | typedef struct p4_pd_packets_meter_spec { 122 | uint32_t cir_pps; 123 | uint32_t cburst_pkts; 124 | uint32_t pir_pps; 125 | uint32_t pburst_pkts; 126 | p4_pd_meter_type_t meter_type; 127 | } p4_pd_packets_meter_spec_t; 128 | 129 | typedef struct p4_pd_bytes_meter_spec { 130 | uint32_t cir_kbps; 131 | uint32_t cburst_kbits; 132 | uint32_t pir_kbps; 133 | uint32_t pburst_kbits; 134 | p4_pd_meter_type_t meter_type; 135 | } p4_pd_bytes_meter_spec_t; 136 | 137 | typedef uint16_t p4_pd_mirror_id_t; 138 | #endif 139 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/src/ofpat_groups.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Ofpat group logic 3 | */ 4 | 5 | #include "ofpat_state.h" 6 | #include "p4_sim/pd.h" 7 | #include "p4_sim/pre.h" 8 | #include "p4_sim/ofpat_groups.h" 9 | #include "p4_sim/ofpat_pipeline.h" 10 | #include "p4ofagent/p4ofagent.h" 11 | #include "p4ofagent/parse.h" 12 | 13 | #define MAX_GROUP_SIZE 32 14 | #define PORT_MAP_LENGTH ((PRE_PORTS_MAX + 7)/8) 15 | 16 | void 17 | ofpat_group_alloc (uint32_t group_id, of_list_bucket_t *buckets, 18 | enum ofp_group_type type) { 19 | uint32_t bucket_sig; 20 | ofpat_pipeline_key_t key; 21 | 22 | Pvoid_t aargs; 23 | PWord_t pv; 24 | 25 | of_bucket_t elt; 26 | of_list_action_t *actions; 27 | int rv; 28 | 29 | uint8_t *port_map; 30 | uint8_t *lag_map; 31 | port_map = P4OFAGENT_MALLOC (PORT_MAP_LENGTH); 32 | lag_map = P4OFAGENT_MALLOC (PORT_MAP_LENGTH); 33 | memset (port_map, 0, PORT_MAP_LENGTH); 34 | memset (lag_map, 0, PORT_MAP_LENGTH); 35 | 36 | mc_mgrp_hdl_t mgrp; 37 | mc_node_hdl_t node_hdl; 38 | 39 | OF_LIST_BUCKET_ITER(buckets, &elt, rv) { 40 | bucket_sig = 0; 41 | aargs = (Pvoid_t) NULL; 42 | actions = of_bucket_actions_get (&elt); 43 | parse_actions (actions, &aargs, &bucket_sig); 44 | 45 | JLG (pv, aargs, OFPAT_OUTPUT); 46 | 47 | *(uint64_t *) port_map |= ((uint64_t) 1 << *(uint32_t *) *pv); 48 | 49 | memset (&key, 0, sizeof (key)); 50 | ofpat_pipeline_key_new (NULL, &group_id, (uint16_t *) *pv, &key); 51 | ofpat_pipeline_add (bucket_sig, &key, &aargs); 52 | } 53 | 54 | mc_mgrp_create (P4_PRE_SESSION, P4_DEVICE_ID, group_id, &mgrp); 55 | mc_node_create (P4_PRE_SESSION, P4_DEVICE_ID, group_id, 56 | port_map, lag_map, &node_hdl); 57 | mc_associate_node (P4_PRE_SESSION, mgrp, node_hdl); 58 | 59 | ofpat_state_group_store_mc (group_id, mgrp, node_hdl); 60 | ofpat_state_group_set_ports (group_id, port_map); 61 | } 62 | 63 | p4_pd_status_t 64 | ofpat_group_create (uint32_t group_id, enum ofp_group_type type) { 65 | p4_pd_entry_hdl_t eh; 66 | p4_pd_status_t status = 0; 67 | ofpat_pipeline_key_t key; 68 | 69 | ofpat_pipeline_key_new (NULL, &group_id, NULL, &key); 70 | 71 | ${p4_pd_prefix}ofpat_group_ingress_match_spec_t ms; 72 | ${p4_pd_prefix}ofpat_group_ingress_mc_action_spec_t as; 73 | 74 | mc_mgrp_hdl_t hdl; 75 | mc_node_hdl_t node; 76 | 77 | ms.openflow_metadata_group_id = group_id; 78 | 79 | if (ofpat_state_group_get_mc (group_id, &hdl, &node)) { 80 | return 1; 81 | } 82 | 83 | as.action_mcindex = hdl; 84 | 85 | status |= ${p4_pd_prefix}ofpat_group_ingress_table_add_with_ofpat_group_ingress_mc 86 | (P4_PD_SESSION, P4_SINGLE_DEVICE, &ms, &as, &eh); 87 | 88 | 89 | ofpat_state_group_store_eh (&key, eh); 90 | 91 | return status; 92 | } 93 | 94 | p4_pd_status_t 95 | ofpat_group_delete (uint32_t group_id, enum ofp_group_type type) { 96 | p4_pd_status_t status = 0; 97 | uint8_t *port_map; 98 | 99 | mc_mgrp_hdl_t mgrp; 100 | mc_node_hdl_t node; 101 | 102 | if (ofpat_state_group_get_mc (group_id, &mgrp, &node)) { 103 | return 1; 104 | } 105 | 106 | if (ofpat_state_group_get_ports (group_id, &port_map)) { 107 | P4_LOG ("Could not get group ports"); 108 | return 1; 109 | } 110 | 111 | mc_mgrp_destroy (P4_PRE_SESSION, mgrp); 112 | mc_node_destroy (P4_PRE_SESSION, node); 113 | 114 | ofpat_pipeline_key_t key; 115 | uint16_t i, j, egr_port; 116 | for (i = 0, j = 0; (j * 8 + i) < PORT_MAP_LENGTH; i = !((i + 1) % 8) ? j++, 0 : i + 1) { 117 | if (*(port_map + j) & (1 << i)) { 118 | egr_port = j * 8 + i; 119 | ofpat_pipeline_key_new (NULL, &group_id, &egr_port, &key); 120 | status |= ofpat_pipeline_del (&key); 121 | ofpat_state_pipeline_delete (&key); 122 | } 123 | } 124 | 125 | free ((void *)port_map); 126 | 127 | return status; 128 | } 129 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/primitives_arith.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PRIMITIVES_ARITH_H 18 | #define _RMT_PRIMITIVES_ARITH_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | static inline void 26 | _MODIFY_FIELD_UINT32(uint8_t *dst_ptr, 27 | uint8_t *src_ptr, int src_len, 28 | uint8_t *mask_ptr, int mask_len) { 29 | uint32_t value = *(uint32_t *) (src_ptr + src_len - sizeof(uint32_t)); 30 | uint32_t mask = *(uint32_t *) (mask_ptr + mask_len - sizeof(uint32_t)); 31 | /* TODO: Leo, why an OR ??? */ 32 | /* value &= mask; */ 33 | /* *(uint32_t *) dst_ptr |= value; */ 34 | *(uint32_t *) dst_ptr = ((*(uint32_t *) dst_ptr) & (~mask)) | (value & mask); 35 | } 36 | 37 | /* mask has to be at least as large as dest */ 38 | static inline void 39 | _MODIFY_FIELD_BYTE_BUF(uint8_t *dst_ptr, int dst_len, 40 | uint8_t *src_ptr, int src_len, 41 | uint8_t *mask_ptr, int mask_len) { 42 | int src_idx; 43 | int dst_idx; 44 | int mask_idx; 45 | 46 | for (src_idx = (src_len <= dst_len) ? 0 : src_len - dst_len, 47 | dst_idx = (dst_len <= src_len) ? 0 : dst_len - src_len, 48 | mask_idx = mask_len - src_len; 49 | src_idx < src_len; 50 | src_idx++, dst_idx++, mask_idx++) 51 | { 52 | dst_ptr[dst_idx] &= ~mask_ptr[dst_idx]; 53 | dst_ptr[dst_idx] |= src_ptr[src_idx] & mask_ptr[mask_idx]; 54 | } 55 | } 56 | 57 | 58 | /* TODO Leo: temporary function with default behavior before Leo comes back and 59 | tests his code.*/ 60 | 61 | static inline void 62 | _ADD_UINT32(uint8_t *dst_ptr, 63 | const uint8_t *src_ptr1, const int src_len1, 64 | const uint8_t *src_ptr2, const int src_len2) { 65 | *(uint32_t *) dst_ptr = htonl(ntohl(*(const uint32_t *) 66 | (src_ptr1 + src_len1 - sizeof(const uint32_t))) + 67 | ntohl(*(const uint32_t *) 68 | (src_ptr2 + src_len2 - sizeof(const uint32_t)))); 69 | } 70 | 71 | static inline void 72 | _SUBTRACT_UINT32(uint8_t *dst_ptr, 73 | const uint8_t *src_ptr1, const int src_len1, 74 | const uint8_t *src_ptr2, const int src_len2) { 75 | *(uint32_t *) dst_ptr = htonl(ntohl(*(const uint32_t *) 76 | (src_ptr1 + src_len1 - sizeof(const uint32_t))) - 77 | ntohl(*(const uint32_t *) 78 | (src_ptr2 + src_len2 - sizeof(const uint32_t)))); 79 | } 80 | 81 | static inline void 82 | _SHIFT_LEFT_UINT32(uint8_t *dst_ptr, 83 | const uint8_t *src_ptr1, const int src_len1, 84 | const uint8_t *src_ptr2, const int src_len2) { 85 | *(uint32_t *) dst_ptr = htonl(ntohl(*(const uint32_t *) 86 | (src_ptr1 + src_len1 - sizeof(const uint32_t))) << 87 | ntohl(*(const uint32_t *) 88 | (src_ptr2 + src_len2 - sizeof(const uint32_t)))); 89 | } 90 | 91 | static inline void 92 | _SHIFT_RIGHT_UINT32(uint8_t *dst_ptr, 93 | const uint8_t *src_ptr1, const int src_len1, 94 | const uint8_t *src_ptr2, const int src_len2) { 95 | *(uint32_t *) dst_ptr = htonl(ntohl(*(const uint32_t *) 96 | (src_ptr1 + src_len1 - sizeof(const uint32_t))) >> 97 | ntohl(*(const uint32_t *) 98 | (src_ptr2 + src_len2 - sizeof(const uint32_t)))); 99 | } 100 | 101 | static inline void 102 | _SUBTRACT_FROM_FIELD_UINT32(uint8_t *dst_ptr, 103 | uint8_t *src_ptr, int src_len) { 104 | *(uint32_t *) dst_ptr = htonl(ntohl(*(uint32_t *) dst_ptr) - ntohl(*(uint32_t *) 105 | (src_ptr + src_len - sizeof(uint32_t)))); 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/calculations.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "field_list.h" 22 | #include "deparser.h" 23 | #include "checksums_algos.h" 24 | #include "rmt_internal.h" 25 | 26 | uint8_t *_buffers[NB_THREADS]; 27 | 28 | void calculations_init() { 29 | int i; 30 | for(i = 0; i < NB_THREADS; i++) { 31 | _buffers[i] = malloc(4096); 32 | } 33 | } 34 | 35 | /* the build_input_* functions return the length of the input */ 36 | //:: for name, c_info in field_list_calculations.items(): 37 | static int build_input_${name}(phv_data_t *phv, uint8_t *buffer) { 38 | uint8_t *dst = buffer; 39 | uint8_t *src; 40 | //:: offset = 0 41 | //:: # input_ is field list 42 | //:: input_ = c_info["input"][0] 43 | //:: field_list = field_lists[input_] 44 | //:: for field in field_list: 45 | //:: type_, value = field 46 | //:: if type_ == "field_ref": 47 | //:: f_info = field_info[value] 48 | //:: byte_offset_phv = f_info["byte_offset_phv"] 49 | src = get_phv_ptr(phv, ${byte_offset_phv}); 50 | //:: d_type = f_info["data_type"] 51 | //:: width = f_info["bit_width"] 52 | //:: if d_type == "uint32_t": 53 | deparse_uint32(dst, src, ${offset}, ${width}); 54 | //:: offset += width 55 | dst += ${offset / 8}; 56 | //:: offset = offset % 8 57 | //:: elif d_type == "byte_buf_t": 58 | //:: assert(width % 8 == 0) 59 | assert(${offset} == 0); 60 | deparse_byte_buf(dst, src, ${width / 8}); 61 | dst += ${width / 8}; 62 | //:: #endif 63 | //:: elif type_ == "header_ref": 64 | //:: h_info = header_info[value] 65 | //:: byte_offset_phv = h_info["byte_offset_phv"] 66 | //:: width = h_info["bit_width"] 67 | src = get_phv_ptr(phv, ${byte_offset_phv}); 68 | _deparse_${value}(src, dst); 69 | dst += ${width / 8}; 70 | //:: elif type_ == "payload": 71 | //:: prev_found = False 72 | //:: for header_instance in ordered_header_instances_regular: 73 | //:: if header_instance == value: 74 | //:: prev_found = True 75 | //:: continue 76 | //:: #endif 77 | //:: if not prev_found: continue 78 | //:: h_info = header_info[header_instance] 79 | //:: byte_offset_phv = h_info["byte_offset_phv"] 80 | //:: width = h_info["bit_width"] 81 | if(phv_is_valid_header(phv, RMT_HEADER_INSTANCE_${header_instance})) { 82 | src = get_phv_ptr(phv, ${byte_offset_phv}); 83 | _deparse_${header_instance}(src, dst); 84 | dst += ${width / 8}; 85 | } 86 | //:: #endfor 87 | memcpy(dst, phv->payload, phv->payload_len); 88 | dst += phv->payload_len; 89 | //:: elif type_ == "integer": 90 | //:: for c in value: 91 | *dst++ = ${c}; 92 | //:: #endfor 93 | //:: else: 94 | //:: print "not supported yet" 95 | //:: assert(False) 96 | //:: #endif 97 | //:: #endfor 98 | return (dst - buffer); 99 | } 100 | 101 | //:: #endfor 102 | 103 | //:: for name, c_info in field_list_calculations.items(): 104 | void calculations_${name}(phv_data_t *phv, uint8_t *result) { 105 | //:: input_size = c_info["input_size"] 106 | uint8_t *buffer = _buffers[phv->id]; 107 | memset(buffer, 0, ${input_size}); 108 | int len = build_input_${name}(phv, buffer); 109 | //:: algo = c_info["algorithm"] 110 | ${algo}(buffer, len, result); 111 | //:: bytes_output = c_info["output_phv_bytes"] 112 | //:: width = c_info["output_width"] 113 | //:: if width < 32: 114 | //:: shift = 8 * bytes_output - width 115 | *(uint32_t *) result = htonl((*(uint32_t *) result) & ((1 << ${shift})-1)); 116 | //:: #endif 117 | } 118 | 119 | //:: #endfor 120 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai/thrift/p4_sai_rpc.thrift: -------------------------------------------------------------------------------- 1 | # P4 SAI thrift definition file 2 | 3 | //:: api_prefix = p4_prefix + "_sai" 4 | 5 | namespace py p4_sai_rpc 6 | namespace cpp p4_sai_rpc 7 | 8 | typedef i32 EntryHandle_t 9 | typedef i32 MemberHandle_t 10 | typedef i32 GroupHandle_t 11 | typedef string MacAddr_t 12 | typedef string IPv6_t 13 | 14 | typedef i32 SessionHandle_t 15 | struct DevTarget_t { 16 | 1: required byte dev_id; 17 | 2: required i16 dev_pipe_id; 18 | } 19 | 20 | 21 | union sai_attribute_value { 22 | 1: bool booldata; 23 | 2: string chardata; 24 | 3: byte u8; 25 | 4: byte s8; 26 | 5: i16 u16; 27 | 6: i16 s16; 28 | 7: i32 u32; 29 | 8: i32 s32; 30 | 9: i64 u64; 31 | 10:i64 s64; 32 | 11:list mac; 33 | /* 34 | 11: sai_mac_t mac; 35 | 12: sai_ip4_t ip4; 36 | 13: sai_ip6_t ip6; 37 | 14: sai_ip_address_t ipaddr; 38 | 15: sai_port_list_t portlist; 39 | 16: sai_next_hop_list_t nhlist; 40 | 17: sai_acl_field_data_t aclfield; 41 | 18: sai_acl_action_data_t acldata; 42 | */ 43 | } 44 | 45 | struct sai_attribute { 46 | 1: i32 id; 47 | 2: sai_attribute_value value; 48 | } 49 | 50 | struct sai_attribute_list { 51 | 1: i32 api_id; // 1 - 13 (SWITCH-HOST_INTERFACE) 52 | 2: i32 count; // Not needed as list count should get us this 53 | 3: list attr_list; 54 | } 55 | 56 | //:: def get_type(byte_width): 57 | //:: if byte_width == 1: 58 | //:: return "byte" 59 | //:: elif byte_width == 2: 60 | //:: return "i16" 61 | //:: elif byte_width <= 4: 62 | //:: return "i32" 63 | //:: elif byte_width == 6: 64 | //:: return "MacAddr_t" 65 | //:: elif byte_width == 16: 66 | //:: return "IPv6_t" 67 | //:: else: 68 | //:: return "string" 69 | //:: #endif 70 | //:: #enddef 71 | //:: 72 | //:: # match_fields is list of tuples (name, type) 73 | //:: def gen_match_params(match_fields, field_info): 74 | //:: params = [] 75 | //:: for field, type in match_fields: 76 | //:: if type == "valid": 77 | //:: params += [(field + "_valid", 1)] 78 | //:: continue 79 | //:: #endif 80 | //:: f_info = field_info[field] 81 | //:: bytes_needed = (f_info["bit_width"] + 7 ) / 8 82 | //:: params += [(field, bytes_needed)] 83 | //:: if type == "lpm": params += [(field + "_prefix_length", 2)] 84 | //:: if type == "ternary": params += [(field + "_mask", bytes_needed)] 85 | //:: #endfor 86 | //:: return params 87 | //:: #enddef 88 | //:: 89 | //:: def gen_action_params(names, byte_widths, _get_type = get_type): 90 | //:: params = [] 91 | //:: for name, width in zip(names, byte_widths): 92 | //:: name = "action_" + name 93 | //:: params += [(name, width)] 94 | //:: #endfor 95 | //:: return params 96 | //:: #enddef 97 | //:: 98 | //:: 99 | 100 | # Match structs 101 | 102 | //:: for table, t_info in table_info.items(): 103 | //:: if not t_info["match_fields"]: 104 | //:: continue 105 | //:: #endif 106 | //:: match_params = gen_match_params(t_info["match_fields"], field_info) 107 | struct ${api_prefix}_${table}_match_spec_t { 108 | //:: id = 1 109 | //:: for name, width in match_params: 110 | //:: type_ = get_type(width) 111 | ${id}: required ${type_} ${name}; 112 | //:: id += 1 113 | //:: #endfor 114 | } 115 | 116 | //:: #endfor 117 | 118 | 119 | service ${api_prefix} { 120 | # Test echo interface 121 | void echo(1:string s); 122 | 123 | # static functions 124 | //:: name = "init" 125 | void ${name}(); 126 | 127 | //:: name = "cleanup" 128 | void ${name}(); 129 | 130 | //:: name = "client_init" 131 | SessionHandle_t ${name}(1:i32 max_txn_size); 132 | 133 | //:: name = "client_cleanup" 134 | i32 ${name}(1:SessionHandle_t sess_hdl); 135 | 136 | //:: for table, t_info in table_info.items(): 137 | // ${table} API thrift interfaces 138 | //:: has_match_spec = len(t_info["match_fields"]) > 0 139 | //:: act_prof_name = t_info["action_profile"] 140 | //:: if act_prof_name is None: 141 | //:: if has_match_spec: 142 | i32 create_${table}(1: ${api_prefix}_${table}_match_spec_t match, 2: sai_attribute_list attr); 143 | i32 delete_${table}(1:${api_prefix}_${table}_match_spec_t match); 144 | //:: else: 145 | i32 create_${table}(1: sai_attribute_list attr); 146 | i32 delete_${table}(); 147 | 148 | //:: #endif 149 | //:: #endif 150 | //:: #endfor 151 | } 152 | 153 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_pre.c: -------------------------------------------------------------------------------- 1 | //:: if enable_pre: 2 | #include 3 | #include 4 | 5 | p4_pd_status_t 6 | p4_pd_mc_create_session(p4_pd_sess_hdl_t *sess_hdl) 7 | { 8 | return mc_create_session(sess_hdl); 9 | } 10 | 11 | p4_pd_status_t 12 | p4_pd_mc_destroy_session(p4_pd_sess_hdl_t sess_hdl) 13 | { 14 | return mc_destroy_session(sess_hdl); 15 | } 16 | 17 | p4_pd_status_t 18 | p4_pd_mc_complete_operations(p4_pd_sess_hdl_t sess_hdl) 19 | { 20 | return mc_complete_operations(sess_hdl); 21 | } 22 | 23 | p4_pd_status_t 24 | p4_pd_mc_mgrp_create(p4_pd_sess_hdl_t sess_hdl, int dev, uint16_t grp, 25 | p4_pd_entry_hdl_t *grp_hdl) 26 | { 27 | return mc_mgrp_create(sess_hdl, dev, grp, grp_hdl); 28 | } 29 | 30 | p4_pd_status_t 31 | p4_pd_mc_mgrp_destroy(p4_pd_sess_hdl_t sess_hdl, int dev, 32 | p4_pd_entry_hdl_t grp_hdl) 33 | { 34 | return mc_mgrp_destroy(sess_hdl, grp_hdl); 35 | } 36 | 37 | p4_pd_status_t 38 | p4_pd_mc_node_create(p4_pd_sess_hdl_t sess_hdl, int dev, uint16_t rid, 39 | uint8_t *port_map, uint8_t *lag_map, 40 | p4_pd_entry_hdl_t *node_hdl) 41 | { 42 | return mc_node_create(sess_hdl, dev, rid, port_map, lag_map, node_hdl); 43 | } 44 | 45 | p4_pd_status_t 46 | p4_pd_mc_node_update(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t node_hdl, 47 | uint8_t *port_map, uint8_t *lag_map) 48 | { 49 | return mc_node_update(sess_hdl, node_hdl, port_map, lag_map); 50 | } 51 | 52 | p4_pd_status_t 53 | p4_pd_mc_node_destroy(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t node_hdl) 54 | { 55 | return mc_node_destroy(sess_hdl, node_hdl); 56 | } 57 | 58 | p4_pd_status_t 59 | p4_pd_mc_associate_node(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t grp_hdl, 60 | p4_pd_entry_hdl_t l1_hdl, uint16_t xid, bool xid_valid) 61 | { 62 | (void) xid; 63 | (void) xid_valid; 64 | return mc_associate_node(sess_hdl, grp_hdl, l1_hdl); 65 | } 66 | 67 | p4_pd_status_t 68 | p4_pd_mc_dissociate_node(p4_pd_sess_hdl_t sess_hdl, int dev, p4_pd_entry_hdl_t grp_hdl, 69 | p4_pd_entry_hdl_t node_hdl) 70 | { 71 | return mc_dissociate_node(sess_hdl, grp_hdl, node_hdl); 72 | } 73 | 74 | p4_pd_status_t 75 | p4_pd_mc_set_lag_membership(p4_pd_sess_hdl_t sess_hdl, int dev, uint8_t lag, 76 | uint8_t *port_map) 77 | { 78 | return mc_set_lag_membership(sess_hdl, dev, lag, port_map); 79 | } 80 | 81 | p4_pd_status_t 82 | p4_pd_mc_ecmp_create(p4_pd_sess_hdl_t session, 83 | int device, 84 | p4_pd_entry_hdl_t *ecmp_hdl) { 85 | (void) session; (void) device; (void) ecmp_hdl; 86 | return 0; 87 | } 88 | 89 | p4_pd_status_t 90 | p4_pd_mc_ecmp_destroy(p4_pd_sess_hdl_t session, 91 | int device, 92 | p4_pd_entry_hdl_t ecmp_hdl) { 93 | (void) session; (void) device; (void) ecmp_hdl; 94 | return 0; 95 | } 96 | 97 | p4_pd_status_t 98 | p4_pd_mc_ecmp_mbr_add(p4_pd_sess_hdl_t session, 99 | int device, 100 | p4_pd_entry_hdl_t ecmp_hdl, 101 | p4_pd_entry_hdl_t l1_hdl) { 102 | (void) session; (void) device; (void) ecmp_hdl; (void) l1_hdl; 103 | return 0; 104 | } 105 | 106 | p4_pd_status_t 107 | p4_pd_mc_ecmp_mbr_rem(p4_pd_sess_hdl_t session, 108 | int device, 109 | p4_pd_entry_hdl_t ecmp_hdl, 110 | p4_pd_entry_hdl_t l1_hdl) { 111 | (void) session; (void) device; (void) ecmp_hdl; (void) l1_hdl; 112 | return 0; 113 | } 114 | 115 | p4_pd_status_t 116 | p4_pd_mc_associate_ecmp(p4_pd_sess_hdl_t session, 117 | int device, 118 | p4_pd_entry_hdl_t grp_hdl, 119 | p4_pd_entry_hdl_t ecmp_hdl, 120 | uint16_t xid, bool xid_valid) { 121 | (void) session; (void) device; (void) grp_hdl; (void) ecmp_hdl; 122 | (void) xid_valid; 123 | return 0; 124 | } 125 | 126 | p4_pd_status_t 127 | p4_pd_mc_dissociate_ecmp(p4_pd_sess_hdl_t session, 128 | int device, 129 | p4_pd_entry_hdl_t grp_hdl, 130 | p4_pd_entry_hdl_t ecmp_hdl) { 131 | (void) session; (void) device; (void) grp_hdl; (void) ecmp_hdl; 132 | return 0; 133 | } 134 | 135 | //:: #endif 136 | -------------------------------------------------------------------------------- /p4c_bm/plugin/of/src/ofpat_state.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFPAT_STATE_H_ 2 | #define _OFPAT_STATE_H_ 3 | 4 | /* 5 | * State management of ofpat.c 6 | */ 7 | 8 | #include "p4_sim/pre.h" 9 | #include "p4_sim/pd.h" 10 | #include "p4_sim/ofpat_pipeline.h" 11 | #include "p4ofagent/openflow-spec1.3.0.h" 12 | 13 | /************************************************************ 14 | * All accessors return void, 1 on failure, or 0 on success * 15 | ************************************************************/ 16 | 17 | /* Deletes the pipeline indexed by key. 18 | * @param key Indexes the pipeline 19 | */ 20 | void 21 | ofpat_state_pipeline_delete (ofpat_pipeline_key_t *key); 22 | 23 | /* Stores an entry handle (flow id) in the pipeline. 24 | * @param key The key for this pipeline 25 | * @param type One of OFPAT 26 | * @param eh The entry handle to store 27 | */ 28 | void 29 | ofpat_state_pipeline_store_eh (ofpat_pipeline_key_t *key, 30 | enum ofp_action_type type, 31 | p4_pd_entry_hdl_t eh); 32 | 33 | /* Get the entry handle in the pipeline indexed by key. 34 | * @param key The key for this pipeline 35 | * @param type One of OFPAT 36 | * @param eh [out] The entry handle to get 37 | */ 38 | int 39 | ofpat_state_pipeline_get_eh (ofpat_pipeline_key_t *key, 40 | enum ofp_action_type type, 41 | p4_pd_entry_hdl_t *eh); 42 | 43 | /* Get the next entry handle after that indexed by type 44 | * in the pipeline indexed by key. 45 | * @param key The key for this pipeline 46 | * @param type [in, out] One of OFPAT 47 | * @param eh [out] The entry handle to store 48 | */ 49 | int 50 | ofpat_state_pipeline_get_next_eh (ofpat_pipeline_key_t *key, 51 | enum ofp_action_type *type, 52 | p4_pd_entry_hdl_t *eh); 53 | 54 | /* Get the next entry handle after that indexed by type in the 55 | * pipeline indexed by key. 56 | * @param key The key for this pipeline 57 | * @param type [in, out] One of OFPAT 58 | * @param eh [out] The entry handle to store 59 | */ 60 | int 61 | ofpat_state_pipeline_get_first_eh (ofpat_pipeline_key_t *key, 62 | enum ofp_action_type *type, 63 | p4_pd_entry_hdl_t *eh); 64 | 65 | /********** 66 | * GROUPS * 67 | **********/ 68 | 69 | /* Associates a group-table entry handle with a group id. 70 | * @param group_id The group id given by the controller 71 | * @param eh The entry handle to store 72 | */ 73 | void 74 | ofpat_state_group_store_eh (ofpat_pipeline_key_t *key, p4_pd_entry_hdl_t eh); 75 | 76 | /* Gets the group-table entry handle associated with a group id. 77 | * @param group_id The group id given by the controller 78 | * @param eh [out] The entry hdl to get 79 | */ 80 | int 81 | ofpat_state_group_get_eh (ofpat_pipeline_key_t *key, p4_pd_entry_hdl_t *eh); 82 | 83 | /* Associates multicast information with a group id. 84 | * @param group_id The group id given by the controller 85 | * @param mgid Multicast group id 86 | * @param l1 L1 node handle 87 | */ 88 | void 89 | ofpat_state_group_store_mc (uint32_t group_id, mc_mgrp_hdl_t mgid, 90 | mc_node_hdl_t l1); 91 | 92 | /* Gets multicast information associated with group id. 93 | * @param group_id The group id given by the controller 94 | * @param mgid [out] Multicast group id 95 | * @param l1 [out] L1 node handle 96 | */ 97 | int 98 | ofpat_state_group_get_mc (uint32_t group_id, mc_mgrp_hdl_t *mgid, 99 | mc_node_hdl_t *l1); 100 | 101 | /* Associates LAG handle with group id. 102 | * @param group_id The group id given by the controller 103 | * @param lag The LAG group handle 104 | */ 105 | void 106 | ofpat_state_group_store_lag (uint32_t group_id, p4_pd_grp_hdl_t lag); 107 | 108 | /* Gets LAG lag associated with group id. 109 | * @param group_id The group id given by the controller 110 | * @param lag [out] The LAG group handle 111 | */ 112 | int 113 | ofpat_state_group_get_lag (uint32_t group_id, p4_pd_grp_hdl_t *lag); 114 | 115 | /* Sets member egress ports */ 116 | void 117 | ofpat_state_group_set_ports (uint32_t group_id, uint8_t *ports); 118 | 119 | /* Gets member egress ports */ 120 | int 121 | ofpat_state_group_get_ports (uint32_t group_id, uint8_t **ports); 122 | 123 | /* Deletes member egress ports entry and frees port list. */ 124 | int 125 | ofpat_state_group_delete_ports (uint32_t group_id); 126 | 127 | #endif /* OFPAT_STATE_H_ */ 128 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pg_int.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef __PG_INT_H 18 | #define __PG_INT_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "portmanager.h" 26 | #define MAX_PGEN_BUFFER_SZ 16384 27 | #define LOCAL_PORT_BITS 7 28 | #define LOCAL_PORT_MASK 0x7F 29 | #define PORT_BITS 9 30 | #define PORT_MASK 0x1FF 31 | #define CACHE_BLK_SIZE 64 32 | #define PGEN_HEADER_SZ 6 33 | #define PORT_COUNT_PER_PIPE_MAX 128 34 | 35 | /* 36 | * Specifies how many "real" usecs does 37 | * every delay element represent 38 | */ 39 | 40 | #define CLK_TIME 300 41 | #define CLK_DONE -1 42 | //#define MAX_PKTGEN_PORT 287 43 | #define MAX_PKTGEN_PORT 512 44 | 45 | 46 | typedef struct pg_port_cfg { 47 | bool recir_en; 48 | bool recir_snoop_en; 49 | bool port_down; 50 | uint8_t down_cnt; 51 | } pg_port_cfg; 52 | 53 | 54 | 55 | typedef struct pg_counter_t { 56 | p4_pd_stat_t batch_cnt; 57 | p4_pd_stat_t pkt_cnt; 58 | p4_pd_stat_t trigger_cnt; 59 | 60 | } pg_counter_t; 61 | 62 | /* 63 | * This struct is used @ generation time 64 | * For each round of generation, so per-trigger 65 | */ 66 | 67 | typedef struct pg_gen_t { 68 | int32_t curr_pkt_clk; 69 | int32_t curr_batch_clk; 70 | uint16_t curr_pkt; 71 | uint16_t curr_batch; 72 | uint32_t cfg_pkt_jitter; 73 | uint32_t cum_pkt_jitter; 74 | uint32_t jitter_pkt_clks; 75 | uint32_t cfg_batch_jitter; 76 | uint32_t jitter_batch_clks; 77 | } pg_gen_t; 78 | 79 | /* 80 | * Defines what caused the trigger 81 | * The triggering event is responsible for populating 82 | * this. The generator is responsible for parsing this 83 | * and generating the appropriate packets. A linked list of 84 | * these events is maintained. 85 | */ 86 | 87 | 88 | typedef struct pg_trigger_t { 89 | tommy_node trigger_node; 90 | pg_gen_t* st_gen; 91 | /* Port number, recirculation header */ 92 | uint32_t trigger_id; 93 | sig_atomic_t n_count; 94 | bool is_done; 95 | }pg_trigger_t; 96 | 97 | 98 | typedef struct pg_app_status_t { 99 | bool is_init; 100 | tommy_list trigger_lst; 101 | } pg_app_status_t; 102 | 103 | 104 | typedef struct pg_app_t { 105 | tommy_node type_hash_node; 106 | tommy_node app_hash_node; 107 | tommy_node app_lst_node; 108 | uint8_t app_id; 109 | sig_atomic_t is_en; 110 | pg_app_status_t* status; 111 | pg_counter_t* counters; 112 | p4_pd_pktgen_app_cfg* cfg; 113 | uint8_t* pkt_buffer; 114 | 115 | } pg_app_t; 116 | 117 | /* 118 | * Thread for pktgen, 1 thread/device 119 | * Passed as argument to each thread 120 | */ 121 | 122 | typedef struct pg_thread_t { 123 | pthread_t thread_id; 124 | int pipe_id; 125 | /* Add other stuff here */ 126 | }pg_thread_t; 127 | 128 | 129 | /* 130 | * Per device gbl_cfg 131 | */ 132 | 133 | typedef struct __attribute__((__aligned__(CACHE_BLK_SIZE))) { 134 | bool pgen_en; 135 | uint8_t *pgen_buf; 136 | pg_port_cfg* g_port_cfg; 137 | pthread_mutex_t cfg_mutex; 138 | tommy_hashlin g_type_hash; 139 | tommy_hashlin g_appid_hash; 140 | tommy_list g_app_lst; 141 | }pg_gbl_cfg; 142 | 143 | 144 | /* Globals */ 145 | extern pg_gbl_cfg* g_pg_gbl_cfg; 146 | 147 | /* Internal APIs */ 148 | 149 | p4_pd_status_t pktgen_app_cfg(int dev_id, uint32_t app_id, p4_pd_pktgen_app_cfg* cfg); 150 | void pktgen_port_flap(int port, bool status); 151 | void pktgen_init(void); 152 | void pktgen_start(int dev); 153 | void pktgen_stop(int dev); 154 | void pktgen_cleanup(void); 155 | void pktgen_alloc_port_cfg(int dev); 156 | 157 | void pktgen_snoop_recirc(int dev, int port, uint8_t* pkt, uint32_t len); 158 | bool pktgen_is_recirc_en(int dev, int port); 159 | 160 | uint16_t pktgen_get_pipe(uint32_t port); 161 | uint16_t pktgen_get_port(uint32_t port); 162 | 163 | 164 | pg_counter_t* pktgen_get_stats(int dev_id, uint32_t app_id); 165 | p4_pd_status_t pktgen_app_arm(int dev_id, uint32_t app_id, bool en); 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai/src/sai_static.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static const char *sai_p4_profile_get_value(_In_ sai_switch_profile_id_t profile_id, 5 | _In_ const char* variable) 6 | { 7 | return variable; 8 | } 9 | 10 | 11 | static int sai_p4_profile_get_next_value(_In_ sai_switch_profile_id_t profile_id, 12 | _Out_ const char** variable, 13 | _Out_ const char** value) 14 | { 15 | return 0; 16 | } 17 | 18 | 19 | static service_method_table_t sai_p4_service_table = { 20 | .profile_get_value = sai_p4_profile_get_value, 21 | .profile_get_next_value = sai_p4_profile_get_next_value 22 | }; 23 | 24 | static sai_switch_api_t *switch_api; 25 | static sai_port_api_t *port_api; 26 | static sai_fdb_api_t *fdb_api; 27 | static sai_router_interface_api_t *router_interface_api; 28 | static sai_virtual_router_api_t *virtual_router_api; 29 | static sai_route_api_t *route_api; 30 | static sai_next_hop_api_t *next_hop_api; 31 | static sai_neighbor_api_t *neighbor_api; 32 | 33 | 34 | 35 | extern void _init_entry_index_hashmap(void); 36 | 37 | void sai_init( void ) 38 | { 39 | _init_entry_index_hashmap(); 40 | sai_api_initialize(0, &sai_p4_service_table); 41 | } 42 | 43 | void sai_simple_setup( void ) 44 | { 45 | // printf("Simple SAI setup\n"); 46 | sai_api_query(SAI_API_SWITCH, (void **)&switch_api); 47 | if(switch_api) { 48 | sai_attribute_t attr1[2]; 49 | attr1[0].id = SAI_SWITCH_ATTR_OPER_STATUS; 50 | attr1[0].value.u32 = 1; 51 | attr1[1].id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; 52 | attr1[1].value.u32 = 0x22222200; 53 | switch_api->create_switch(2, attr1); 54 | } 55 | 56 | sai_api_query(SAI_API_PORT, (void **)&port_api); 57 | if(port_api) { 58 | sai_port_entry_t port1 = {1}; 59 | sai_attribute_t attr1[2]; 60 | attr1[0].id = SAI_PORT_ATTR_OPER_STATUS; 61 | attr1[0].value.u32 = 1; 62 | attr1[1].id = SAI_PORT_ATTR_FDB_LEARNING; 63 | attr1[1].value.u32 = 2; 64 | port_api->create_port(&port1, 2, attr1); 65 | } 66 | 67 | sai_api_query(SAI_API_ROUTER_INTERFACE, (void **)&router_interface_api); 68 | if(router_interface_api) { 69 | sai_router_interface_entry_t router1 = {{0x00, 0x12, 0x34, 0x56, 0x78, 0x90}}; 70 | sai_attribute_t attr1[2]; 71 | attr1[0].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID; 72 | attr1[0].value.u32 = 2; 73 | attr1[1].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID; 74 | attr1[1].value.u32 = 10; 75 | router_interface_api->create_router_interface(&router1, 2, attr1); 76 | } 77 | 78 | sai_api_query(SAI_API_FDB, (void **)&fdb_api); 79 | if(fdb_api) { 80 | sai_fdb_entry_t fdb1 = {0, {0x00, 0x11, 0x11, 0x11, 0x11, 0x11}}; 81 | sai_attribute_t attr1; 82 | attr1.id = SAI_FDB_ATTR_PORT_ID; 83 | attr1.value.u32 = 2; 84 | fdb_api->create_fdb(&fdb1, 1, &attr1); 85 | } 86 | 87 | sai_api_query(SAI_API_VIRTUAL_ROUTER, (void **)&virtual_router_api); 88 | if(virtual_router_api) { 89 | sai_virtual_router_entry_t virtual_router1 = {10}; 90 | sai_attribute_t attr1[2]; 91 | attr1[0].id = SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE; 92 | attr1[0].value.u32 = 1; 93 | attr1[1].id = SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS; 94 | attr1[1].value.u32 = 0x22222200; 95 | virtual_router_api->create_virtual_router(&virtual_router1, 2, attr1); 96 | } 97 | 98 | sai_api_query(SAI_API_ROUTE, (void **)&route_api); 99 | if(route_api) { 100 | sai_route_entry_t route1 = {10, 0x0a000001}; 101 | sai_attribute_t attr1; 102 | attr1.id = SAI_ROUTE_ATTR_NEXT_HOP_ID; 103 | attr1.value.u32 = 1; 104 | route_api->create_route(&route1, 1, &attr1); 105 | } 106 | 107 | sai_api_query(SAI_API_NEXT_HOP, (void **)&next_hop_api); 108 | if(next_hop_api) { 109 | sai_next_hop_entry_t nexthop1 = {1}; 110 | sai_attribute_t attr1; 111 | attr1.id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; 112 | attr1.value.u32 = 2; 113 | next_hop_api->create_next_hop(&nexthop1, 1, &attr1); 114 | } 115 | 116 | sai_api_query(SAI_API_NEIGHBOR, (void **)&neighbor_api); 117 | if(neighbor_api) { 118 | sai_neighbor_entry_t neighbor1 = {10, 0x0a000001, 2}; 119 | sai_attribute_t attr1[2]; 120 | attr1[0].id = SAI_NEIGHBOR_ATTR_PORT_ID; 121 | attr1[0].value.u32 = 3; 122 | attr1[1].id = SAI_NEIGHBOR_ATTR_DST_MAC_ADDRESS; 123 | attr1[1].value.u32 = 2; 124 | neighbor_api->create_neighbor(&neighbor1, 2, attr1); 125 | } 126 | } 127 | 128 | 129 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/metadata_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "parser.h" 18 | #include "deparser.h" 19 | #include "queuing.h" 20 | #include "enums.h" 21 | #include "pipeline.h" 22 | #include "metadata_recirc.h" 23 | #include "mirroring_internal.h" 24 | 25 | static void metadata_extract_full(uint8_t *meta, uint8_t *hdr) { 26 | //:: for header_instance in ordered_header_instances_non_virtual: 27 | //:: h_info = header_info[header_instance] 28 | //:: is_metadata = h_info["is_metadata"] 29 | //:: if not is_metadata: continue 30 | _extract_${header_instance}(meta, hdr); 31 | hdr += ${h_info["bit_width"] / 8}; 32 | meta += ${h_info["byte_width_phv"]}; 33 | //:: #endfor 34 | } 35 | 36 | void metadata_extract(uint8_t *meta, uint8_t *hdr, 37 | int *metadata_recirc) { 38 | if(!metadata_recirc) return metadata_extract_full(meta, hdr); 39 | metadata_recirc_set_t *metadata_set = metadata_recirc_init(metadata_recirc); 40 | uint8_t *src; 41 | //:: for header_instance in ordered_header_instances_non_virtual: 42 | //:: h_info = header_info[header_instance] 43 | //:: is_metadata = h_info["is_metadata"] 44 | //:: if not is_metadata: continue 45 | //:: bytes = h_info["bit_width"] / 8 46 | //:: for field in h_info["fields"]: 47 | //:: f_info = field_info[field] 48 | //:: d_type = f_info["data_type"] 49 | //:: byte_offset_phv = f_info["byte_offset_phv"] 50 | //:: byte_offset_hdr = f_info["byte_offset_hdr"] 51 | //:: bit_offset_hdr = f_info["bit_offset_hdr"] 52 | //:: mask = f_info["mask"] 53 | //:: byte_width_phv = f_info["byte_width_phv"] 54 | //:: width = f_info["bit_width"] 55 | if(metadata_recirc_is_valid(metadata_set, RMT_FIELD_INSTANCE_${field})) { 56 | RMT_LOG(P4_LOG_LEVEL_TRACE, "metadata_extract: extracting metadata field ${field}\n"); 57 | src = hdr + ${byte_offset_hdr}; 58 | //:: if d_type == "uint32_t": 59 | EXTRACT_UINT32(meta, src, ${bit_offset_hdr}, ${width}); 60 | //:: elif d_type == "byte_buf_t": 61 | EXTRACT_BYTE_BUF(meta, src, ${byte_width_phv}); 62 | //:: #endif 63 | } 64 | meta += ${byte_width_phv}; 65 | //:: #endfor 66 | // Moving |hdr| to end of ${header_instance}. 67 | hdr += ${bytes}; 68 | //:: #endfor 69 | 70 | free(metadata_set); 71 | } 72 | 73 | void metadata_dump(uint8_t *hdr, uint8_t *src) { 74 | //:: for header_instance in ordered_header_instances_non_virtual: 75 | //:: h_info = header_info[header_instance] 76 | //:: is_metadata = h_info["is_metadata"] 77 | //:: if not is_metadata: continue 78 | _deparse_${header_instance}(src, hdr); 79 | hdr += ${h_info["bit_width"] / 8}; 80 | src += ${h_info["byte_width_phv"]}; 81 | //:: #endfor 82 | } 83 | 84 | //:: for name, binding in metadata_name_map.items(): 85 | uint32_t metadata_get_${name}(uint8_t *metadata) { 86 | return ntohl(*(uint32_t *) (metadata + ${metadata_offsets[binding]})); 87 | } 88 | 89 | void metadata_set_${name}(uint8_t *metadata, uint32_t value) { 90 | *(uint32_t *) (metadata + ${metadata_offsets[binding]}) = htonl(value); 91 | } 92 | 93 | //:: #endfor 94 | 95 | 96 | //:: if enable_intrinsic : 97 | //:: for name, binding in intrinsic_metadata_name_map.items(): 98 | uint32_t metadata_get_${name}(uint8_t *metadata) { 99 | return ntohl(*(uint32_t *) (metadata + ${metadata_offsets[binding]})); 100 | } 101 | 102 | void metadata_set_${name}(uint8_t *metadata, uint32_t value) { 103 | *(uint32_t *) (metadata + ${metadata_offsets[binding]}) = htonl(value); 104 | } 105 | //:: #endfor 106 | //:: #endif 107 | 108 | //:: if enable_pre : 109 | //:: for name, binding in pre_metadata_name_map.items(): 110 | uint32_t metadata_get_${name}(uint8_t *metadata) { 111 | return ntohl(*(uint32_t *) (metadata + ${metadata_offsets[binding]})); 112 | } 113 | 114 | void metadata_set_${name}(uint8_t *metadata, uint32_t value) { 115 | *(uint32_t *) (metadata + ${metadata_offsets[binding]}) = htonl(value); 116 | } 117 | //:: #endfor 118 | //:: #endif 119 | 120 | //:: for name, binding in extra_metadata_name_map.items(): 121 | uint32_t metadata_get_${name}(uint8_t *metadata) { 122 | return ntohl(*(uint32_t *) (metadata + ${metadata_offsets[binding]})); 123 | } 124 | 125 | void metadata_set_${name}(uint8_t *metadata, uint32_t value) { 126 | *(uint32_t *) (metadata + ${metadata_offsets[binding]}) = htonl(value); 127 | } 128 | //:: #endfor 129 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/checksums.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "checksums.h" 20 | #include "phv.h" 21 | #include "fields.h" 22 | #include "primitives.h" 23 | //#include "calculations.h" 24 | #include "rmt_internal.h" 25 | 26 | /* Condition functions */ 27 | 28 | //:: for idx, cond in enumerate(calculated_fields_conds): 29 | static int check_condition_${idx + 1}(phv_data_t *phv) { 30 | /* this code is copied from conditional_tables.c. TODO unify and test */ 31 | //:: num_registers = len(cond) 32 | /* 33 | We are assuming that each instruction uses 1 register and they numbering 34 | starts with 0. 35 | */ 36 | uint32_t reg[${num_registers}]; 37 | 38 | //:: for instruction in cond: 39 | //:: dest_reg, operation, v1 = instruction[:3] 40 | //:: if len(instruction) > 3: v2 = instruction[3] 41 | //:: if operation == "assign_immediate": 42 | ${dest_reg} = (uint32_t) ${v1}; 43 | //:: elif operation == "assign_field": 44 | ${dest_reg} = phv_buf_field_uint32_get(phv, rmt_field_byte_offset_phv(RMT_FIELD_INSTANCE_${v1})); 45 | ${dest_reg} = ntohl(${dest_reg}); 46 | //:: elif operation == "not": 47 | ${dest_reg} = !${v1}; 48 | //:: elif operation == "or": 49 | ${dest_reg} = ${v1} || ${v2}; 50 | //:: elif operation == "and": 51 | ${dest_reg} = ${v1} && ${v2}; 52 | //:: elif operation == "==": 53 | ${dest_reg} = ${v1} == ${v2}; 54 | //:: elif operation == "!=": 55 | ${dest_reg} = ${v1} != ${v2}; 56 | //:: elif operation == "valid_header": 57 | ${dest_reg} = phv_is_valid_header(phv, RMT_HEADER_INSTANCE_${v1}); 58 | //:: elif operation == "valid_field": 59 | ${dest_reg} = phv_is_valid_field(phv, RMT_FIELD_INSTANCE_${v1}); 60 | //:: else: 61 | //:: assert(False) 62 | //:: #endif 63 | //:: #endfor 64 | 65 | return reg[0]; 66 | } 67 | 68 | //:: #endfor 69 | /* End of condition functions */ 70 | 71 | //:: for field, verifies in calculated_fields_verify.items(): 72 | //:: f_info = field_info[field] 73 | //:: byte_offset_phv = f_info["byte_offset_phv"] 74 | //:: for idx, verify in enumerate(verifies): 75 | //:: calculation, _ = verify 76 | //:: c_info = field_list_calculations[calculation] 77 | //:: bytes_output = c_info["output_phv_bytes"] 78 | static int verify_${field}_${idx}(phv_data_t *phv) { 79 | uint8_t computed[${bytes_output}]; 80 | calculations_${calculation}(phv, computed); 81 | uint8_t *field = get_phv_ptr(phv, ${byte_offset_phv}); 82 | int result = cmp_values(computed, field, ${bytes_output}, NULL); 83 | return result; 84 | } 85 | 86 | //:: #endfor 87 | //:: #endfor 88 | 89 | //:: for field, updates in calculated_fields_update.items(): 90 | //:: f_info = field_info[field] 91 | //:: byte_offset_phv = f_info["byte_offset_phv"] 92 | //:: dst_mask = f_info["mask"] 93 | //:: for idx, update in enumerate(updates): 94 | //:: calculation, _ = update 95 | //:: c_info = field_list_calculations[calculation] 96 | //:: bytes_output = c_info["output_phv_bytes"] 97 | static void update_${field}_${idx}(phv_data_t *phv) { 98 | uint8_t computed[${bytes_output}]; 99 | calculations_${calculation}(phv, computed); 100 | uint8_t *field = get_phv_ptr(phv, ${byte_offset_phv}); 101 | SET_FIELD(field, computed, ${bytes_output}, ${bytes_output}, ${dst_mask}); 102 | } 103 | 104 | //:: #endfor 105 | //:: #endfor 106 | 107 | int verify_checksums(phv_data_t *phv) { 108 | int ret = 1; 109 | //:: for field, verifies in calculated_fields_verify.items(): 110 | //:: for idx, verify in enumerate(verifies): 111 | //:: _, if_cond_idx = verify 112 | //:: if if_cond_idx: 113 | if(check_condition_${if_cond_idx}(phv)) { 114 | ret &= verify_${field}_${idx}(phv); 115 | } 116 | //:: else: 117 | ret &= verify_${field}_${idx}(phv); 118 | //:: break 119 | //:: #endif 120 | 121 | //:: #endfor 122 | //:: #endfor 123 | return ret; 124 | } 125 | 126 | void update_checksums(phv_data_t *phv) { 127 | //:: for field, updates in calculated_fields_update.items(): 128 | //:: for idx, update in enumerate(updates): 129 | //:: _, if_cond_idx = update 130 | //:: if if_cond_idx: 131 | if(check_condition_${if_cond_idx}(phv)) { 132 | update_${field}_${idx}(phv); 133 | } 134 | //:: else: 135 | update_${field}_${idx}(phv); 136 | //:: break 137 | //:: #endif 138 | 139 | //:: #endfor 140 | //:: #endfor 141 | } 142 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/checksums_algos.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_CHECKSUMS_ALGOS_H 18 | #define _RMT_CHECKSUMS_ALGOS_H 19 | 20 | #include 21 | #include "crc_tables.h" 22 | 23 | static inline void csum16(uint8_t *buf, int len, uint8_t *result) { 24 | uint64_t sum = 0; 25 | uint64_t *b = (uint64_t *) buf; 26 | 27 | uint32_t t1, t2; 28 | uint16_t t3, t4; 29 | 30 | /* Main loop - 8 bytes at a time */ 31 | while (len >= sizeof(uint64_t)) 32 | { 33 | uint64_t s = *b++; 34 | sum += s; 35 | if (sum < s) sum++; 36 | len -= 8; 37 | } 38 | 39 | /* Handle tail less than 8-bytes long */ 40 | buf = (uint8_t *) b; 41 | if (len & 4) 42 | { 43 | uint32_t s = *(uint32_t *)buf; 44 | sum += s; 45 | if (sum < s) sum++; 46 | buf += 4; 47 | } 48 | 49 | if (len & 2) 50 | { 51 | uint16_t s = *(uint16_t *) buf; 52 | sum += s; 53 | if (sum < s) sum++; 54 | buf += 2; 55 | } 56 | 57 | if (len & 1) 58 | { 59 | uint8_t s = *(uint8_t *) buf; 60 | sum += s; 61 | if (sum < s) sum++; 62 | } 63 | 64 | /* Fold down to 16 bits */ 65 | t1 = sum; 66 | t2 = sum >> 32; 67 | t1 += t2; 68 | if (t1 < t2) t1++; 69 | t3 = t1; 70 | t4 = t1 >> 16; 71 | t3 += t4; 72 | if (t3 < t4) t3++; 73 | 74 | *(uint16_t *) result = ntohs(~t3); 75 | } 76 | 77 | static inline void csum16_slow(uint8_t *buf, int len, uint8_t *result) { 78 | uint32_t sum = 0; 79 | while(len > 1) { 80 | sum += *((uint16_t *) buf); 81 | buf += 2; 82 | if (sum & (1 << 31)) 83 | sum = (sum & 0xFFFF) + (sum >> 16); 84 | len -= 2; 85 | } 86 | 87 | if(len) 88 | sum += (uint16_t) *(uint8_t *) buf; 89 | 90 | while(sum >> 16) 91 | sum = (sum >> 16) + (sum & 0xFFFF); 92 | 93 | *(uint16_t *) result = htons((uint16_t) (~sum)); 94 | } 95 | 96 | static inline void xor16(uint8_t *buf, int len, uint8_t *result) { 97 | uint16_t xor = 0; 98 | while(len > 1) { 99 | xor ^= *((uint16_t *) buf); 100 | buf += 2; 101 | len -= 2; 102 | } 103 | 104 | if(len) 105 | xor ^= (uint16_t) *(uint8_t *) buf; 106 | 107 | *(uint16_t *) result = xor; 108 | } 109 | 110 | /* This code was adapted from: 111 | http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code */ 112 | 113 | static inline uint32_t reflect(uint32_t data, int nBits) { 114 | uint32_t reflection = 0x00000000; 115 | int bit; 116 | 117 | /* 118 | * Reflect the data about the center bit. 119 | */ 120 | for (bit = 0; bit < nBits; ++bit) { 121 | /* 122 | * If the LSB bit is set, set the reflection of it. 123 | */ 124 | if (data & 0x01) { 125 | reflection |= (1 << ((nBits - 1) - bit)); 126 | } 127 | data = (data >> 1); 128 | } 129 | 130 | return reflection; 131 | } 132 | 133 | /* TODO: try to implement something a bit more generic that will cover 134 | programmable CRCs */ 135 | 136 | static inline void crc16(uint8_t *buf, int len, uint8_t *result) { 137 | int byte; 138 | uint16_t remainder = 0x0000; 139 | uint16_t final_xor_value = 0x0000; 140 | int data; 141 | for(byte = 0; byte < len; byte++) { 142 | data = reflect(buf[byte], 8) ^ (remainder >> 8); 143 | remainder = table_crc16[data] ^ (remainder << 8); 144 | } 145 | *(uint16_t *) result = (reflect(remainder, 16) ^ final_xor_value); 146 | } 147 | 148 | static inline void crcCCITT(uint8_t *buf, int len, uint8_t *result) { 149 | int byte; 150 | uint16_t remainder = 0xFFFF; 151 | uint16_t final_xor_value = 0x0000; 152 | int data; 153 | for(byte = 0; byte < len; byte++) { 154 | data = buf[byte] ^ (remainder >> 8); 155 | remainder = table_crcCCITT[data] ^ (remainder << 8); 156 | } 157 | *(uint16_t *) result = (remainder ^ final_xor_value); 158 | } 159 | 160 | static inline void crc32(uint8_t *buf, int len, uint8_t *result) { 161 | int byte; 162 | uint32_t remainder = 0xFFFFFFFF; 163 | uint32_t final_xor_value = 0xFFFFFFFF; 164 | int data; 165 | for(byte = 0; byte < len; byte++) { 166 | data = reflect(buf[byte], 8) ^ (remainder >> 24); 167 | remainder = table_crc16[data] ^ (remainder << 8); 168 | } 169 | *(uint32_t *) result = (reflect(remainder, 32) ^ final_xor_value); 170 | } 171 | 172 | static inline void identity(uint8_t *buf, int len, uint8_t *result) { 173 | int byte; 174 | int max_len = (len > 4) ? 4 : len; 175 | for(byte = 0; byte < max_len; byte++) { 176 | result[byte] = buf[byte]; 177 | } 178 | } 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai/src/sai.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sai.c 3 | * base implementation 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | extern p4_pd_sess_hdl_t sess_hdl ; 16 | extern p4_pd_dev_target_t dev_tgt; 17 | extern uint8_t dev_id; 18 | 19 | extern sai_switch_api_t switch_api; 20 | extern sai_port_api_t port_api; 21 | extern sai_fdb_api_t fdb_api; 22 | extern sai_router_interface_api_t *router_interface_api; 23 | extern sai_virtual_router_api_t *virtual_router_api; 24 | extern sai_route_api_t *route_api; 25 | extern sai_next_hop_api_t *next_hop_api; 26 | extern sai_neighbor_api_t *neighbor_api; 27 | 28 | 29 | /* 30 | const char *sai_p4_profile_get_value(_In_ sai_switch_profile_id_t profile_id, 31 | _In_ const char* variable) 32 | { 33 | return variable; 34 | } 35 | 36 | 37 | int sai_p4_profile_get_next_value(_In_ sai_switch_profile_id_t profile_id, 38 | _Out_ const char** variable, 39 | _Out_ const char** value) 40 | { 41 | return 0; 42 | } 43 | 44 | 45 | static service_method_table_t sai_p4_service_table = { 46 | .profile_get_value = sa_p4_profile_get_value, 47 | .profile_get_next_value = sai_p4_profile_get_next_value 48 | }; 49 | */ 50 | 51 | p4_pd_status_t 52 | p4_mac_learn_notify_cb(p4_pd_sess_hdl_t sess_hdl, 53 | p4_pd_sai_p4_mac_learn_digest_digest_msg_t *msg, 54 | void *client_data) 55 | { 56 | unsigned int i=0; 57 | p4_pd_entry_hdl_t entry_hdl; 58 | p4_pd_sai_p4_learn_notify_match_spec_t match_spec; 59 | p4_pd_sai_p4_mac_learn_digest_digest_entry_t *entry = msg->entries; 60 | p4_pd_sai_p4_fdb_match_spec_t match_spec1; 61 | p4_pd_sai_p4_fdb_set_action_spec_t action_spec; 62 | 63 | printf("Learn callback\n"); 64 | memset(&match_spec, 0, sizeof(match_spec)); 65 | memset(&match_spec1, 0, sizeof(match_spec1)); 66 | memset(&action_spec, 0, sizeof(action_spec)); 67 | for(i=0;inum_entries;i++, entry++) { 68 | match_spec.intrinsic_metadata_ingress_port = entry->intrinsic_metadata_ingress_port; 69 | match_spec.ingress_metadata_vlan_id = entry->ingress_metadata_vlan_id; 70 | memcpy(match_spec.eth_srcAddr, entry->eth_srcAddr, 6); 71 | p4_pd_sai_p4_learn_notify_table_add_with_nop ( sess_hdl, dev_tgt, &match_spec, &entry_hdl); 72 | // setup fdb 73 | if(entry->ingress_metadata_learning > 1) { 74 | match_spec1.ingress_metadata_vlan_id = entry->ingress_metadata_vlan_id; 75 | memcpy(match_spec1.eth_dstAddr, entry->eth_srcAddr, 6); 76 | action_spec.action_port_id = entry->intrinsic_metadata_ingress_port; 77 | p4_pd_sai_p4_fdb_table_add_with_fdb_set (sess_hdl, dev_tgt, &match_spec1, &action_spec, &entry_hdl); 78 | } 79 | } 80 | return 0; 81 | } 82 | 83 | sai_status_t sai_api_initialize( 84 | _In_ uint64_t flags, 85 | _In_ const service_method_table_t* services 86 | ) 87 | { 88 | p4_pd_entry_hdl_t entry_hdl; 89 | p4_pd_sai_p4_router_interface_set_default_action_router_interface_miss(sess_hdl, dev_tgt, &entry_hdl); 90 | p4_pd_sai_p4_learn_notify_set_default_action_generate_learn_notify(sess_hdl, dev_tgt, &entry_hdl); 91 | 92 | // setup a learn callback 93 | p4_pd_sai_p4_mac_learn_digest_register(sess_hdl, (uint8_t)dev_id, p4_mac_learn_notify_cb, NULL); 94 | return 0; 95 | } 96 | 97 | sai_status_t sai_api_query( 98 | _In_ sai_api_t sai_api_id, 99 | _Out_ void** api_method_table 100 | ) 101 | { 102 | switch(sai_api_id) { 103 | case SAI_API_SWITCH: 104 | *api_method_table = &switch_api; 105 | break; 106 | case SAI_API_PORT: 107 | *api_method_table = &port_api; 108 | break; 109 | case SAI_API_FDB: 110 | *api_method_table = &fdb_api; 111 | break; 112 | case SAI_API_VIRTUAL_ROUTER: 113 | *api_method_table = &virtual_router_api; 114 | break; 115 | case SAI_API_ROUTE: 116 | *api_method_table = &route_api; 117 | break; 118 | break; 119 | case SAI_API_NEXT_HOP: 120 | *api_method_table = &next_hop_api; 121 | break; 122 | break; 123 | case SAI_API_ROUTER_INTERFACE: 124 | { 125 | *api_method_table = &router_interface_api; 126 | } 127 | break; 128 | case SAI_API_NEIGHBOR: 129 | *api_method_table = &neighbor_api; 130 | break; 131 | case SAI_API_VLAN: 132 | break; 133 | case SAI_API_NEXT_HOP_GROUP: 134 | break; 135 | case SAI_API_QOS: 136 | break; 137 | case SAI_API_ACL: 138 | break; 139 | case SAI_API_HOST_INTERFACE: 140 | break; 141 | default: 142 | return -1; 143 | } 144 | return 0; 145 | } 146 | 147 | sai_status_t sai_api_uninitialize( void) 148 | { 149 | return 0; 150 | } 151 | 152 | 153 | sai_status_t sai_log_set( 154 | _In_ sai_api_t sai_api_id, 155 | _In_ sai_log_level_t log_level 156 | ) 157 | { 158 | return 0; 159 | } 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/tcam_cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "tcam_cache.h" 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | typedef struct cache_entry_s{ 30 | time_t last_access; 31 | uint8_t *key; 32 | int key_size; /* all the keys have to be the same size, this just make the 33 | code slightly simpler */ 34 | void *data; 35 | tommy_hashtable_node node; 36 | } cache_entry_t; 37 | 38 | struct tcam_cache_s { 39 | pthread_mutex_t lock; 40 | int size; 41 | int key_size; 42 | int expiration_secs; 43 | int nb_entries; 44 | cache_entry_t *entries; 45 | unsigned long *bitmap_used; 46 | int bitmap_size; 47 | tommy_hashtable hashtable; 48 | }; 49 | 50 | static inline int cmp (const void *arg, const void *obj) { 51 | return memcmp(arg, 52 | ((cache_entry_t *) obj)->key, 53 | ((cache_entry_t *) obj)->key_size); 54 | } 55 | 56 | tcam_cache_t *tcam_cache_create(int size, int key_size, int expiration_secs) { 57 | tcam_cache_t *cache = malloc(sizeof(tcam_cache_t)); 58 | cache->bitmap_size = ((size + 63) / 64); 59 | cache->size = cache->bitmap_size * size; 60 | cache->key_size = key_size; 61 | cache->expiration_secs = expiration_secs; 62 | cache->nb_entries = 0; 63 | cache->entries = calloc(cache->size, sizeof(cache_entry_t)); 64 | tommy_hashtable_init(&cache->hashtable, 2 * cache->size); 65 | cache->bitmap_used = calloc(cache->bitmap_size, sizeof(unsigned long)); 66 | pthread_mutex_init(&cache->lock, NULL); 67 | return cache; 68 | }; 69 | 70 | void tcam_cache_destroy(tcam_cache_t *cache) { 71 | tommy_hashtable_done(&cache->hashtable); 72 | free(cache->entries); 73 | free(cache->bitmap_used); 74 | free(cache); 75 | } 76 | 77 | /* 0: found, 78 | 1: not found, insert 79 | 2: not found, do NOT insert 80 | */ 81 | int tcam_cache_lookup(tcam_cache_t *cache, uint8_t *key, void **data) { 82 | int acquired = pthread_mutex_trylock(&cache->lock); 83 | if(acquired){ 84 | *data = NULL; 85 | return 2; 86 | } 87 | uint32_t hash = hashlittle(key, cache->key_size, 0); 88 | cache_entry_t *entry = tommy_hashtable_search(&cache->hashtable, 89 | cmp, 90 | key, 91 | hash); 92 | int result; 93 | if(entry) { 94 | entry->last_access = time(NULL); 95 | *data = entry->data; 96 | result = 0; 97 | } 98 | else { 99 | *data = NULL; 100 | result = 1; 101 | } 102 | pthread_mutex_unlock(&cache->lock); 103 | return result; 104 | } 105 | 106 | /* 0: inserted 107 | 1: not enough space in cache 108 | */ 109 | int tcam_cache_insert(tcam_cache_t *cache, uint8_t *key, void *data) { 110 | pthread_mutex_lock(&cache->lock); 111 | if(cache->nb_entries == cache->size) { 112 | pthread_mutex_unlock(&cache->lock); 113 | return 1; 114 | } 115 | int i; 116 | cache_entry_t *entry = NULL; 117 | int trailing_ones; 118 | for(i = 0; i < cache->bitmap_size; i++) { 119 | trailing_ones = __builtin_ctzl(~cache->bitmap_used[i]); 120 | if(trailing_ones != sizeof(unsigned long)) { 121 | entry = &cache->entries[sizeof(unsigned long) * i + trailing_ones]; 122 | cache->bitmap_used[i] |= (1 << trailing_ones); 123 | break; 124 | } 125 | } 126 | 127 | entry->last_access = time(NULL); 128 | entry->key = key; 129 | entry->key_size = cache->key_size; 130 | entry->data = data; 131 | uint32_t hash = hashlittle(key, cache->key_size, 0); 132 | tommy_hashtable_insert(&cache->hashtable, &entry->node, entry, hash); 133 | cache->nb_entries++; 134 | pthread_mutex_unlock(&cache->lock); 135 | return 0; 136 | } 137 | 138 | int tcam_cache_purge(tcam_cache_t *cache) { 139 | int removed = 0; 140 | pthread_mutex_lock(&cache->lock); 141 | 142 | int i, j; 143 | cache_entry_t *entry; 144 | time_t now = time(NULL); 145 | unsigned long used; 146 | int trailing_zeros; 147 | for(i = 0; i < cache->bitmap_size; i++) { 148 | used = cache->bitmap_used[i]; 149 | trailing_zeros = __builtin_ctzl(used); 150 | for(j = trailing_zeros; j < sizeof(unsigned long); j++) { 151 | if(used & (1 << j)){ 152 | entry = &cache->entries[sizeof(unsigned long) * i + j]; 153 | if ((now - entry->last_access) > cache->expiration_secs) { 154 | cache->bitmap_used[i] &= ~(1 << j); 155 | tommy_hashtable_remove_existing(&cache->hashtable, &entry->node); 156 | removed++; 157 | } 158 | } 159 | } 160 | } 161 | 162 | cache->nb_entries -= removed; 163 | pthread_mutex_unlock(&cache->lock); 164 | 165 | return removed; 166 | } 167 | 168 | void tcam_cache_invalidate(tcam_cache_t *cache) { 169 | pthread_mutex_lock(&cache->lock); 170 | 171 | tommy_hashtable_empty(&cache->hashtable); 172 | memset(cache->bitmap_used, 0, cache->bitmap_size * sizeof(unsigned long)); 173 | cache->nb_entries = 0; 174 | 175 | pthread_mutex_unlock(&cache->lock); 176 | } 177 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/pd_ms.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include "pd_ms.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #define NUM_DEVICES 256 25 | 26 | /* typedef Pvoid_t mbr_to_act_map_t; */ 27 | /* typedef Pvoid_t mbr_to_grp_list_map_t; */ 28 | 29 | struct p4_pd_ms_table_state_s { 30 | Pvoid_t devices_mbr_to_grp_list[NUM_DEVICES]; 31 | Pvoid_t devices_mbr_to_act[NUM_DEVICES]; 32 | Pvoid_t devices_grp_to_act[NUM_DEVICES]; 33 | }; 34 | 35 | //:: _action_profiles = set() 36 | //:: for table, t_info in table_info.items(): 37 | //:: act_prof = t_info["action_profile"] 38 | //:: if act_prof is None: continue 39 | //:: if act_prof in _action_profiles: continue 40 | //:: _action_profiles.add(act_prof) 41 | p4_pd_ms_table_state_t ms_${act_prof}_state; 42 | //:: #endfor 43 | 44 | void p4_pd_ms_init(void) { 45 | //:: _action_profiles = set() 46 | //:: for table, t_info in table_info.items(): 47 | //:: act_prof = t_info["action_profile"] 48 | //:: if act_prof is None: continue 49 | //:: if act_prof in _action_profiles: continue 50 | //:: _action_profiles.add(act_prof) 51 | memset(ms_${act_prof}_state.devices_mbr_to_grp_list, 0, NUM_DEVICES * sizeof(Pvoid_t)); 52 | memset(ms_${act_prof}_state.devices_mbr_to_act, 0, NUM_DEVICES * sizeof(Pvoid_t)); 53 | memset(ms_${act_prof}_state.devices_grp_to_act, 0, NUM_DEVICES * sizeof(Pvoid_t)); 54 | //:: #endfor 55 | } 56 | 57 | int p4_pd_ms_add_mbr_to_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 58 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_grp_hdl_t grp_hdl) { 59 | PWord_t PValue; 60 | JLG(PValue, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 61 | int Rc_int; 62 | Pvoid_t *jarray_grps = (Pvoid_t *) PValue; 63 | J1S(Rc_int, *jarray_grps, grp_hdl); 64 | return Rc_int; 65 | } 66 | 67 | int p4_pd_ms_del_mbr_from_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 68 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_grp_hdl_t grp_hdl) { 69 | PWord_t PValue; 70 | JLG(PValue, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 71 | int Rc_int; 72 | Pvoid_t *jarray_grps = (Pvoid_t *) PValue; 73 | J1U(Rc_int, *jarray_grps, grp_hdl); 74 | return Rc_int; 75 | } 76 | 77 | void p4_pd_ms_mbr_apply_to_grps(p4_pd_ms_table_state_t *state, uint8_t dev_id, 78 | p4_pd_mbr_hdl_t mbr_hdl, 79 | PDMSGrpFn grp_fn, void *aux) { 80 | PWord_t PValue; 81 | JLG(PValue, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 82 | Word_t Index = 0; 83 | int Rc_int; 84 | Pvoid_t *jarray_grps = (Pvoid_t *) PValue; 85 | J1F(Rc_int, *jarray_grps, Index); 86 | while(Rc_int) { 87 | grp_fn(dev_id, mbr_hdl, Index, aux); 88 | J1N(Rc_int, *jarray_grps, Index); 89 | } 90 | } 91 | 92 | void p4_pd_ms_new_mbr(p4_pd_ms_table_state_t *state, uint8_t dev_id, 93 | p4_pd_mbr_hdl_t mbr_hdl) { 94 | PWord_t PValue; 95 | JLI(PValue, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 96 | assert(!(*PValue)); 97 | } 98 | 99 | void p4_pd_ms_del_mbr(p4_pd_ms_table_state_t *state, uint8_t dev_id, 100 | p4_pd_mbr_hdl_t mbr_hdl) { 101 | PWord_t PValue; 102 | JLG(PValue, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 103 | Word_t num_freed; 104 | Pvoid_t *jarray_grps = (Pvoid_t *) PValue; 105 | J1FA(num_freed, *jarray_grps); 106 | (void) num_freed; 107 | int Rc_int; 108 | JLD(Rc_int, state->devices_mbr_to_grp_list[dev_id], mbr_hdl); 109 | assert(Rc_int); 110 | } 111 | 112 | p4_pd_act_hdl_t p4_pd_ms_get_mbr_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 113 | p4_pd_mbr_hdl_t mbr_hdl) { 114 | p4_pd_act_hdl_t *PValue; 115 | JLG(PValue, state->devices_mbr_to_act[dev_id], mbr_hdl); 116 | return *PValue; 117 | } 118 | 119 | void p4_pd_ms_set_mbr_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 120 | p4_pd_mbr_hdl_t mbr_hdl, p4_pd_act_hdl_t act_hdl) { 121 | p4_pd_act_hdl_t *PValue; 122 | JLI(PValue, state->devices_mbr_to_act[dev_id], mbr_hdl); 123 | *PValue = act_hdl; 124 | } 125 | 126 | p4_pd_act_hdl_t p4_pd_ms_get_grp_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 127 | p4_pd_grp_hdl_t grp_hdl) { 128 | p4_pd_act_hdl_t *PValue; 129 | JLG(PValue, state->devices_grp_to_act[dev_id], grp_hdl); 130 | return *PValue; 131 | } 132 | 133 | void p4_pd_ms_set_grp_act(p4_pd_ms_table_state_t *state, uint8_t dev_id, 134 | p4_pd_grp_hdl_t grp_hdl, p4_pd_act_hdl_t act_hdl) { 135 | p4_pd_act_hdl_t *PValue; 136 | JLI(PValue, state->devices_grp_to_act[dev_id], grp_hdl); 137 | *PValue = act_hdl; 138 | } 139 | 140 | /* not very efficient, I have to loop over all members */ 141 | void p4_pd_ms_del_grp(p4_pd_ms_table_state_t *state, uint8_t dev_id, 142 | p4_pd_grp_hdl_t grp_hdl) { 143 | Word_t Index = 0; 144 | PWord_t PValue; 145 | int Rc_int; 146 | Pvoid_t *jarray_grps; 147 | JLF(PValue, state->devices_mbr_to_grp_list[dev_id], Index); 148 | while(PValue != NULL) { 149 | jarray_grps = (Pvoid_t *) PValue; 150 | J1U(Rc_int, *jarray_grps, grp_hdl); 151 | JLN(PValue, state->devices_mbr_to_grp_list[dev_id], Index); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /p4c_bm/plugin/sai/inc/sai.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Microsoft Open Technologies, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR 9 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 10 | * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS 11 | * FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 12 | * 13 | * See the Apache Version 2.0 License for specific language governing 14 | * permissions and limitations under the License. 15 | * 16 | * Microsoft would like to thank the following companies for their review and 17 | * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, 18 | * Dell Products, L.P., Facebook, Inc 19 | * 20 | * Module Name: 21 | * 22 | * sai.h 23 | * 24 | * Abstract: 25 | * 26 | * This module defines an entry point into Switch Abstraction Interfrace (SAI) 27 | * 28 | */ 29 | #if !defined (__SAI_H_) 30 | #define __SAI_H_ 31 | 32 | #include 33 | /* 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | */ 49 | /* 50 | * 51 | * Defined API sets have assigned ID's. If specific api method table changes 52 | * in any way (method signature, number of methods), a new ID needs to be 53 | * created (e.g. VLAN2) and old API still may need to be supported for 54 | * compatibility with older adapter hosts. 55 | * 56 | */ 57 | typedef enum _sai_api_t 58 | { 59 | SAI_API_UNSPECIFIED = 0, 60 | SAI_API_SWITCH = 1, /* sai_switch_api_t */ 61 | SAI_API_PORT = 2, /* sai_port_api_t */ 62 | SAI_API_FDB = 3, /* sai_fdb_api_t */ 63 | SAI_API_VLAN = 4, /* sai_vlan_api_t */ 64 | SAI_API_VIRTUAL_ROUTER = 5, /* sai_virtual_router_api_t */ 65 | SAI_API_ROUTE = 6, /* sai_route_api_t */ 66 | SAI_API_NEXT_HOP = 7, /* sai_next_hop_api_t */ 67 | SAI_API_NEXT_HOP_GROUP = 8, /* sai_next_hop_group_api_t */ 68 | SAI_API_ROUTER_INTERFACE = 9, /* sai_router_interface_api_t */ 69 | SAI_API_NEIGHBOR = 10, /* sai_neighbor_api_t */ 70 | SAI_API_QOS = 11, /* sai_qos_api_t */ 71 | SAI_API_ACL = 12, /* sai_acl_api_t */ 72 | SAI_API_HOST_INTERFACE = 13, /* sai_host_interface_api_t */ 73 | } sai_api_t; 74 | 75 | typedef enum _sai_log_level_t 76 | { 77 | SAI_LOG_DEBUG = 1, 78 | SAI_LOG_INFO = 2, 79 | SAI_LOG_WARN = 3, 80 | SAI_LOG_ERROR = 4, 81 | SAI_LOG_CRITICAL = 5 82 | } sai_log_level_t; 83 | 84 | /* 85 | * Method table that contains function pointers for services exposed by adapter 86 | * host for adapter. 87 | */ 88 | 89 | typedef struct _service_method_table_t 90 | { 91 | /* Get variable value given its name */ 92 | const char* (*profile_get_value)(_In_ sai_switch_profile_id_t profile_id, 93 | _In_ const char* variable); 94 | 95 | /* Enumerate all the K/V pairs in a profile. 96 | Pointer to NULL passed as variable restarts enumeration. 97 | Function returns 0 if next value exists, -1 at the end of the list. */ 98 | int (*profile_get_next_value)(_In_ sai_switch_profile_id_t profile_id, 99 | _Out_ const char** variable, 100 | _Out_ const char** value); 101 | 102 | } service_method_table_t; 103 | 104 | 105 | 106 | /* 107 | * Routine Description: 108 | * Adapter module initialization call. This is NOT for SDK initialization. 109 | * 110 | * Arguments: 111 | * [in] flags - reserved for future use, must be zero 112 | * [in] services - methods table with services provided by adapter host 113 | * 114 | * Return Values: 115 | * SAI_STATUS_SUCCESS on success 116 | * Failure status code on error 117 | */ 118 | sai_status_t 119 | sai_api_initialize( 120 | _In_ uint64_t flags, 121 | _In_ const service_method_table_t* services 122 | ); 123 | 124 | 125 | /* 126 | * Routine Description: 127 | * Retrieve a pointer to the C-style method table for desired SAI 128 | * functionality as specified by the given sai_api_id. 129 | * 130 | * Arguments: 131 | * [in] sai_api_id - SAI api ID 132 | * [out] api_method_table - Caller allocated method table 133 | * The table must remain valid until the sai_api_uninitialize() is called 134 | * 135 | * Return Values: 136 | * SAI_STATUS_SUCCESS on success 137 | * Failure status code on error 138 | */ 139 | sai_status_t 140 | sai_api_query( 141 | _In_ sai_api_t sai_api_id, 142 | _Out_ void** api_method_table 143 | ); 144 | 145 | 146 | /* 147 | * Routine Description: 148 | * Uninitialization of the adapter module. SAI functionalities, retrieved via 149 | * sai_api_query() cannot be used after this call. 150 | * 151 | * Arguments: 152 | * None 153 | * 154 | * Return Values: 155 | * SAI_STATUS_SUCCESS on success 156 | * Failure status code on error 157 | */ 158 | sai_status_t 159 | sai_api_uninitialize( 160 | void 161 | ); 162 | 163 | /* 164 | * Routine Description: 165 | * Set log level for sai api module. The default log level is SAI_LOG_WARN. 166 | * 167 | * Arguments: 168 | * [in] sai_api_id - SAI api ID 169 | * [in] log_level - log level 170 | * 171 | * Return Values: 172 | * SAI_STATUS_SUCCESS on success 173 | * Failure status code on error 174 | */ 175 | sai_status_t 176 | sai_log_set( 177 | _In_ sai_api_t sai_api_id, 178 | _In_ sai_log_level_t log_level 179 | ); 180 | #endif // __SAI_H_ 181 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/queuing.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "queuing.h" 20 | #include "metadata_utils.h" 21 | #include "parser.h" 22 | #include "deparser.h" 23 | #include "enums.h" 24 | #include "pipeline.h" 25 | #include "metadata_recirc.h" 26 | #include "mirroring_internal.h" 27 | #include "pre_internal.h" 28 | 29 | //:: pd_prefix = "p4_pd_" + p4_prefix + "_" 30 | 31 | typedef struct queuing_pkt_s { 32 | buffered_pkt_t pkt; 33 | uint8_t *metadata; 34 | int *metadata_recirc; 35 | } queuing_pkt_t; 36 | 37 | #define QUEUING_CB_SIZE 1024 38 | 39 | circular_buffer_t *rmt_queuing_cb; /* only 1 */ 40 | 41 | pthread_t queuing_thread; 42 | 43 | uint8_t *metadata; 44 | 45 | //:: bytes = 0 46 | //:: for header_instance in ordered_header_instances_non_virtual: 47 | //:: h_info = header_info[header_instance] 48 | //:: is_metadata = h_info["is_metadata"] 49 | //:: if is_metadata: bytes += h_info["byte_width_phv"] 50 | //:: #endfor 51 | 52 | //:: if enable_pre: 53 | static int pre_replication(queuing_pkt_t *q_pkt, uint8_t *metadata) 54 | { 55 | int replication = 0; 56 | buffered_pkt_t *b_pkt = &q_pkt->pkt; 57 | 58 | uint16_t eg_mcast_group = metadata_get_eg_mcast_group(metadata); 59 | if (eg_mcast_group) { 60 | RMT_LOG(P4_LOG_LEVEL_VERBOSE, "replicating packets\n"); 61 | mc_process_and_replicate(eg_mcast_group, metadata, q_pkt->metadata_recirc, b_pkt); 62 | // Free the packet once it is replicated 63 | free(b_pkt->pkt_data); 64 | free(q_pkt->metadata); 65 | free(q_pkt->metadata_recirc); 66 | free(q_pkt); 67 | replication = 1; 68 | } 69 | return replication; 70 | } 71 | //:: #endif 72 | 73 | static void *pkt_processing_loop(void *arg) { 74 | while(1) { 75 | queuing_pkt_t *q_pkt = (queuing_pkt_t *) cb_read(rmt_queuing_cb); 76 | buffered_pkt_t *b_pkt = &q_pkt->pkt; 77 | RMT_LOG(P4_LOG_LEVEL_TRACE, "queuing system: packet dequeued\n"); 78 | memset(metadata, 0, ${bytes}); 79 | metadata_extract(metadata, q_pkt->metadata, q_pkt->metadata_recirc); 80 | 81 | /* after this point, no one should use q_pkt->metadata */ 82 | 83 | int mirror_id = metadata_get_clone_spec(metadata); 84 | metadata_set_clone_spec(metadata, 0); 85 | int egress_port; 86 | //:: if enable_pre: 87 | if (pre_replication(q_pkt, metadata)) { 88 | continue; 89 | } 90 | //:: #endif 91 | if(mirror_id == 0) { 92 | egress_port = metadata_get_egress_spec(metadata); 93 | /* TODO: formalize somewhere that 511 is the drop port for this target */ 94 | //:: if "ingress_drop_ctl" in extra_metadata_name_map: 95 | // program uses the separate ingress_drop_ctl register 96 | // a non-zero value means drop 97 | if(egress_port == 511 || metadata_get_ingress_drop_ctl(metadata)) { 98 | //:: else: 99 | if(egress_port == 511) { 100 | //:: #endif 101 | RMT_LOG(P4_LOG_LEVEL_VERBOSE, "dropping packet at ingress\n"); 102 | free(b_pkt->pkt_data); 103 | free(q_pkt->metadata); 104 | free(q_pkt->metadata_recirc); 105 | free(q_pkt); 106 | continue; 107 | } 108 | } 109 | else { 110 | RMT_LOG(P4_LOG_LEVEL_VERBOSE, "mirror id is %d\n", mirror_id); 111 | egress_port = p4_pd_mirroring_mapping_get_egress_port(mirror_id); 112 | if (egress_port < 0) { 113 | RMT_LOG(P4_LOG_LEVEL_WARN, 114 | "no mapping for mirror id %d, dropping packet\n", mirror_id); 115 | free(b_pkt->pkt_data); 116 | free(q_pkt->metadata); 117 | free(q_pkt->metadata_recirc); 118 | free(q_pkt); 119 | continue; 120 | } 121 | RMT_LOG(P4_LOG_LEVEL_TRACE, 122 | "queuing system: cloned packet, mirror_id -> egress_port : %d -> %d\n", 123 | mirror_id, egress_port); 124 | } 125 | metadata_set_egress_port(metadata, egress_port); 126 | RMT_LOG(P4_LOG_LEVEL_TRACE, "egress port set to %d\n", egress_port); 127 | 128 | pkt_instance_type_t instance_type = b_pkt->instance_type; 129 | metadata_set_instance_type(metadata, instance_type); 130 | RMT_LOG(P4_LOG_LEVEL_TRACE, "instance type set to %d\n", instance_type); 131 | 132 | //:: if enable_intrinsic: 133 | /* Set enqueue metadata */ 134 | metadata_set_enq_qdepth(metadata, egress_pipeline_count(egress_port)); 135 | metadata_set_enq_timestamp(metadata, get_timestamp()); 136 | //:: #endif 137 | 138 | metadata_dump(q_pkt->metadata, metadata); 139 | egress_pipeline_receive(egress_port, 140 | q_pkt->metadata, q_pkt->metadata_recirc, 141 | b_pkt->pkt_data, b_pkt->pkt_len, b_pkt->pkt_id, 142 | b_pkt->instance_type); 143 | free(q_pkt); 144 | } 145 | 146 | return NULL; 147 | } 148 | 149 | void queuing_init(void) { 150 | rmt_queuing_cb = cb_init(QUEUING_CB_SIZE, CB_WRITE_BLOCK, CB_READ_BLOCK); 151 | 152 | metadata = malloc(${bytes}); 153 | 154 | //:: if enable_pre: 155 | mc_pre_init(); 156 | //:: #endif 157 | pthread_create(&queuing_thread, NULL, 158 | pkt_processing_loop, NULL); 159 | } 160 | 161 | int queuing_receive(uint8_t *metadata, int *metadata_recirc, 162 | void *pkt, int len, uint64_t packet_id, 163 | pkt_instance_type_t instance_type) { 164 | queuing_pkt_t *q_pkt = malloc(sizeof(queuing_pkt_t)); 165 | buffered_pkt_t *b_pkt = &q_pkt->pkt; 166 | q_pkt->metadata = metadata; 167 | q_pkt->metadata_recirc = metadata_recirc; 168 | b_pkt->instance_type = instance_type; 169 | b_pkt->pkt_data = pkt; 170 | b_pkt->pkt_len = len; 171 | b_pkt->pkt_id = packet_id; 172 | cb_write(rmt_queuing_cb, q_pkt); 173 | return 0; 174 | } 175 | -------------------------------------------------------------------------------- /p4c_bm/templates/src/phv.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013-present Barefoot Networks, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _RMT_PHV_H 18 | #define _RMT_PHV_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "string.h" 27 | #include "enums.h" 28 | #include "rmt_internal.h" 29 | #include "metadata_recirc.h" 30 | 31 | /* Regular has to come before metadata !*/ 32 | //:: header_length = 0 33 | //:: metadata_length = 0 34 | //:: for header in ordered_header_instances_metadata: 35 | //:: metadata_length += header_info[header]["byte_width_phv"] 36 | //:: #endfor 37 | //:: for header in ordered_header_instances_regular: 38 | //:: header_length += header_info[header]["byte_width_phv"] 39 | //:: #endfor 40 | #define PHV_LENGTH ${phv_length} 41 | #define PHV_HEADER_START 0 42 | #define PHV_HEADER_LENGTH ${header_length} 43 | #define PHV_METADATA_START (PHV_HEADER_START + PHV_HEADER_LENGTH) 44 | #define PHV_METADATA_LENGTH ${metadata_length} 45 | 46 | typedef uint8_t* byte_buf_t; 47 | 48 | typedef struct phv_data_s { 49 | int id; /* ID of this PHV / pipeline */ 50 | uint64_t packet_id; /* ID of the packet being processed */ 51 | int pipeline_type; /* RMT_PIPELINE_INGRESS or RMT_PIPELINE_EGRESS */ 52 | int deparser_drop_signal; /* Only valid for egress deparser, set to 1 by DROP */ 53 | int resubmit_signal; 54 | metadata_recirc_set_t *metadata_resubmit; /* if not NULL, resubmit */ 55 | uint8_t *headers; 56 | uint8_t *payload; /* Everything that was not extracted by the parser */ 57 | int payload_len; 58 | rmt_header_instance_t *header_virtual_instances; 59 | rmt_field_instance_t *field_virtual_instances; 60 | bool headers_valid[RMT_HEADER_INSTANCE_COUNT]; 61 | metadata_recirc_set_t *metadata_recirc; 62 | int last_entry_hit; /* for direct registers */ 63 | uint32_t truncated_length; 64 | } phv_data_t; 65 | 66 | //:: num_virtual_headers = len(ordered_header_instances_virtual) 67 | #define PHV_GET_HEADER(phv, hdr) \ 68 | ((hdr > ${num_virtual_headers}) ? hdr : phv->header_virtual_instances[hdr]) 69 | 70 | //:: num_virtual_fields = len(ordered_field_instances_virtual) 71 | static inline 72 | rmt_field_instance_t PHV_GET_FIELD(phv_data_t *phv, rmt_field_instance_t field) { 73 | return ((field > ${num_virtual_fields}) ? field : phv->field_virtual_instances[field]); 74 | } 75 | 76 | /* Extract a uint32 container. Note that the uint32 containers are also stored 77 | in network byte order. To perform the shift (for byte alignment), we convert 78 | to host byte order and then back to network byte order. There is probably 79 | room for improvement here. */ 80 | 81 | /* This is maybe too conservative (to please Valgrind). Given the assumptions we 82 | made on header alignment, we should be able to remove some of the tests, even 83 | if Valgrind signals an invalid read / write */ 84 | #define BYTE_ROUND_UP(x) ((x + 7) >> 3) 85 | static inline void EXTRACT_UINT32(uint8_t *dst, uint8_t *src, int bit_offset, int width) { 86 | int i; 87 | for (i = 0; i < BYTE_ROUND_UP(width) - 1; i++) { 88 | dst[i] = (src[i] << bit_offset) | (src[i + 1] >> (8 - bit_offset)); 89 | } 90 | dst[i] = src[i] << bit_offset; 91 | if((bit_offset + width) > (BYTE_ROUND_UP(width) << 3)) { 92 | dst[i] |= (src[i + 1] >> (8 - bit_offset)); 93 | } 94 | for (i = i + 1; i < 4; i++) { 95 | dst[i] = 0; 96 | } 97 | *(uint32_t *) dst = htonl(ntohl(*(uint32_t *) dst) >> (32 - width)); 98 | } 99 | 100 | /* Extract a byte_buf container. We assume these containers to be already byte 101 | aligned (in the incoming packet). */ 102 | 103 | static inline void *EXTRACT_BYTE_BUF(void *dst, const void *src, size_t len) { 104 | return memcpy(dst, src, len); 105 | } 106 | 107 | static inline uint8_t *get_phv_ptr(phv_data_t *phv, int offset) { 108 | return phv->headers + offset; 109 | } 110 | 111 | static inline void phv_buf_field_uint32_set(phv_data_t *phv, 112 | int byte_offset_phv, 113 | uint32_t value) { 114 | *(uint32_t *)get_phv_ptr(phv, byte_offset_phv) = value; 115 | } 116 | 117 | static inline void phv_buf_field_byte_buf_set(phv_data_t *phv, 118 | int byte_offset_phv, 119 | byte_buf_t value, 120 | size_t len) { 121 | memcpy(get_phv_ptr(phv, byte_offset_phv), value, len); 122 | } 123 | 124 | static inline uint32_t phv_buf_field_uint32_get(phv_data_t *phv, 125 | int byte_offset_phv) { 126 | return *(uint32_t *)get_phv_ptr(phv, byte_offset_phv); 127 | } 128 | 129 | static inline byte_buf_t phv_buf_field_byte_buf_get(phv_data_t *phv, 130 | int byte_offset_phv) { 131 | return get_phv_ptr(phv, byte_offset_phv); 132 | } 133 | 134 | static inline void phv_set_valid_header(phv_data_t *phv, 135 | rmt_header_instance_t header_instance) { 136 | phv->headers_valid[header_instance] = 1; 137 | } 138 | 139 | static inline void phv_set_invalid_header(phv_data_t *phv, 140 | rmt_header_instance_t header_instance) { 141 | phv->headers_valid[header_instance] = 0; 142 | } 143 | 144 | static inline int phv_is_valid_header(phv_data_t *phv, 145 | rmt_header_instance_t header_instance){ 146 | return phv->headers_valid[header_instance]; 147 | } 148 | 149 | static inline void phv_set_recirc_metadata_field(phv_data_t *phv, 150 | rmt_field_instance_t field){ 151 | metadata_recirc_add_field(phv->metadata_recirc, field); 152 | } 153 | 154 | static inline void phv_set_recirc_metadata_header(phv_data_t *phv, 155 | rmt_header_instance_t header){ 156 | metadata_recirc_add_header(phv->metadata_recirc, header); 157 | } 158 | 159 | phv_data_t *phv_init(int phv_id, int pipeline_type); 160 | 161 | void phv_clean(phv_data_t *phv); 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /p4c_bm/shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import argparse 18 | import os 19 | import sys 20 | from p4_hlir.main import HLIR 21 | import smart 22 | import shutil 23 | from pkg_resources import resource_string 24 | import json 25 | 26 | 27 | def get_parser(): 28 | parser = argparse.ArgumentParser(description='p4c-behavioral arguments') 29 | parser.add_argument('source', metavar='source', type=str, 30 | help='a source file to include in the P4 program') 31 | 32 | parser.add_argument('--dump_yaml', action='store_true', default = False, 33 | help='dump yaml representation of smart dictionary') 34 | parser.add_argument('--debug', action='store_true', default = False, 35 | help='debugging mode') 36 | parser.add_argument('--optimize', action='store_true', default = False, 37 | help='optimized mode') 38 | parser.add_argument('--with-tcam-cache', 39 | action='store_true', default = False, 40 | help='using experimental tcam cache for lookups') 41 | parser.add_argument('--with-cheap-tcam', 42 | action='store_true', default = False, 43 | help='using experimental (and buggy) tcam implementation') 44 | parser.add_argument('--thrift', action='store_true', default = False, 45 | help='Generate and include thrift interfaces') 46 | parser.add_argument('--gen-dir', dest='gen_dir', default = "output", 47 | help="destination directory for generated files") 48 | parser.add_argument('--p4-name', type=str, dest='p4_name', 49 | help='The name to use for the program') 50 | parser.add_argument('--p4-prefix', type=str, dest='p4_prefix', 51 | help='The name to use for the runtime APIs') 52 | parser.add_argument('--public-inc-path', dest='public_inc_path', default="", 53 | help="Path to use for rmt.h, pd.h, ... references") 54 | parser.add_argument('--meta-config', dest='meta_config', 55 | default = "", 56 | help="Path to json file specifying metadata config") 57 | parser.add_argument('--plugin', dest='plugin_list', action="append", 58 | default = [], 59 | help="list of plugins to generate templates") 60 | parser.add_argument('--plugin-path', dest='plugin_path', type=str, 61 | default = "", 62 | help="Base path where the plugin is located " 63 | "without the plugin name") 64 | parser.add_argument('--openflow-mapping-dir', 65 | help="Directory of openflow mapping files") 66 | parser.add_argument('--openflow-mapping-mod', 67 | help="Openflow mapping module name -- not a file name") 68 | return parser 69 | 70 | def _get_p4_basename(p4_source): 71 | return os.path.splitext(os.path.basename(p4_source))[0] 72 | 73 | def _validate_dir(dir_name): 74 | if not os.path.isdir(args.gen_dir): 75 | print args.gen_dir, "is not a valid directory" 76 | sys.exit(1) 77 | return os.path.abspath(args.gen_dir) 78 | 79 | def main(): 80 | parser = get_parser() 81 | input_args = sys.argv[1:] 82 | args, unparsed_args = parser.parse_known_args() 83 | 84 | has_remaining_args = False 85 | preprocessor_args = [] 86 | for a in unparsed_args: 87 | if a[:2] == "-D": 88 | input_args.remove(a) 89 | preprocessor_args.append(a) 90 | else: 91 | has_remaining_args = True 92 | 93 | # trigger error 94 | if has_remaining_args: 95 | parser.parse_args(input_args) 96 | 97 | gen_dir = os.path.abspath(args.gen_dir) 98 | if os.path.exists(gen_dir): 99 | if not os.path.isdir(gen_dir): 100 | sys.stderr.write(args.gen_dir + " exists but is not a directory\n") 101 | sys.exit(1) 102 | else: 103 | try: 104 | os.mkdir(gen_dir) 105 | except: 106 | sys.stderr.write("Could not create output directory %s\n" % 107 | args.gen_dir) 108 | sys.exit(1) 109 | 110 | if args.p4_name: 111 | p4_name = args.p4_name 112 | else: 113 | p4_name = _get_p4_basename(args.source) 114 | 115 | if args.p4_prefix: 116 | p4_prefix = args.p4_prefix 117 | else: 118 | p4_prefix = p4_name 119 | 120 | h = HLIR(args.source) 121 | h.add_preprocessor_args("-D__TARGET_BM__") 122 | for parg in preprocessor_args: 123 | h.add_preprocessor_args(parg) 124 | # in addition to standard P4 primitives 125 | more_primitives = json.loads(resource_string(__name__, 'primitives.json')) 126 | h.add_primitives(more_primitives) 127 | 128 | if not h.build(): 129 | print "Error while building HLIR" 130 | sys.exit(1) 131 | 132 | print "Generating files in directory", gen_dir 133 | 134 | render_dict = smart.render_dict_create(h, 135 | p4_name, p4_prefix, 136 | args.meta_config, 137 | args.public_inc_path, 138 | dump_yaml = args.dump_yaml) 139 | render_dict['hlir'] = h 140 | 141 | if args.openflow_mapping_dir and args.openflow_mapping_mod: 142 | sys.path.append(args.openflow_mapping_dir) 143 | render_dict['openflow_mapping_mod'] = args.openflow_mapping_mod 144 | 145 | smart.render_all_files(render_dict, gen_dir, 146 | with_thrift = args.thrift, 147 | with_plugin_list = args.plugin_list, 148 | with_plugin_path = args.plugin_path) 149 | 150 | if __name__ == "__main__": 151 | main() 152 | -------------------------------------------------------------------------------- /p4c-bm.mk: -------------------------------------------------------------------------------- 1 | THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | ifndef P4FACTORY 4 | $(error P4FACTORY not defined) 5 | endif 6 | MAKEFILES_DIR := $(P4FACTORY)/makefiles 7 | 8 | ifndef SUBMODULE_P4C_BEHAVIORAL 9 | $(error SUBMODULE_P4C_BEHAVIORAL not defined) 10 | endif 11 | 12 | ifndef P4_NAME 13 | $(error P4_NAME not defined) 14 | endif 15 | 16 | ifndef P4_PREFIX 17 | P4_PREFIX := ${P4_NAME} 18 | endif 19 | 20 | # Behavioral compiler; default is to use the one in local submodule 21 | BM_SHELL := ${SUBMODULE_P4C_BEHAVIORAL}/p4c_bm/shell.py 22 | 23 | BM_BUILD_DIR := ${BUILD_DIR}/bm 24 | BM_OBJ_DIR := ${BM_BUILD_DIR}/obj 25 | BM_BUILD_SRC_DIR := ${BM_BUILD_DIR}/src 26 | BM_BUILD_THRIFT_DIR := ${BM_BUILD_DIR}/thrift 27 | 28 | MAKE_DIR := ${BM_BUILD_DIR} 29 | include $(MAKEFILES_DIR)/makedir.mk 30 | 31 | MAKE_DIR := ${BM_OBJ_DIR} 32 | include $(MAKEFILES_DIR)/makedir.mk 33 | 34 | MAKE_DIR := $(BM_BUILD_SRC_DIR) 35 | include $(MAKEFILES_DIR)/makedir.mk 36 | 37 | MAKE_DIR := $(PUBLIC_INC_PATH)/p4_sim 38 | include $(MAKEFILES_DIR)/makedir.mk 39 | 40 | BM_PARAMS := --gen-dir=${BM_BUILD_DIR}/ --thrift --public-inc-path=$(PUBLIC_INC_PATH)/p4_sim 41 | 42 | BM_PARAMS += --p4-prefix=${P4_PREFIX} 43 | 44 | ifdef BM_P4_META_CONFIG 45 | BM_PARAMS += --meta-config=${BM_P4_META_CONFIG} 46 | endif 47 | 48 | BM_TEMPLATES_C := $(wildcard ${THIS_DIR}/p4c_bm/templates/src/*.c) 49 | BM_TEMPLATES_H := $(wildcard ${THIS_DIR}/p4c_bm/templates/src/*.h) 50 | BM_TEMPLATES_H += $(wildcard ${THIS_DIR}/p4c_bm/templates/src/*.ipp) 51 | BM_TEMPLATES_CPP := $(wildcard ${THIS_DIR}/p4c_bm/templates/src/*.cpp) 52 | BM_TEMPLATES_PUBLIC_HEADERS := $(wildcard ${THIS_DIR}/p4c_bm/templates/inc/*.h) 53 | BM_TEMPLATES_THRIFT := $(wildcard ${THIS_DIR}/p4c_bm/templates/thrift/*.thrift) 54 | BM_TEMPLATES := ${BM_TEMPLATES_C} ${BM_TEMPLATES_H} ${BM_TEMPLATES_CPP} ${BM_TEMPLATES_PUBLIC_HEADERS} ${BM_TEMPLATES_THRIFT} 55 | 56 | # compile the plugins 57 | include $(THIS_DIR)/p4c_bm/plugin/p4c-plugin.mk 58 | 59 | BM_TENJIN_OUTPUT_C := $(addprefix ${BM_BUILD_SRC_DIR}/, $(notdir ${BM_TEMPLATES_C})) 60 | BM_TENJIN_OUTPUT_H := $(addprefix ${BM_BUILD_DIR}/src/, $(notdir ${BM_TEMPLATES_H})) 61 | BM_TENJIN_OUTPUT_CPP += $(addprefix ${BM_BUILD_DIR}/src/, $(notdir ${BM_TEMPLATES_CPP})) 62 | PD_PUBLIC_HEADERS_DIR := ${PUBLIC_INC_PATH}/p4_sim 63 | BM_TENJIN_OUTPUT_PUBLIC_HEADERS := $(addprefix ${PD_PUBLIC_HEADERS_DIR}/, $(notdir ${BM_TEMPLATES_PUBLIC_HEADERS})) 64 | 65 | THRIFT_FILES_WITH_SERVICES = p4_pd_rpc conn_mgr_pd_rpc mc_pd_rpc devport_mgr_pd_rpc 66 | THRIFT_FILES = ${THRIFT_FILES_WITH_SERVICES} res 67 | THRIFT_SERVICES = ${P4_PREFIX} conn_mgr mc devport_mgr 68 | THRIFT_PD_BASENAMES = $(addsuffix _constants, ${THRIFT_FILES}) 69 | THRIFT_PD_BASENAMES += $(addsuffix _types, ${THRIFT_FILES}) 70 | THRIFT_PD_BASENAMES += ${THRIFT_SERVICES} 71 | 72 | BM_TENJIN_OUTPUT_THRIFT = $(addprefix ${BM_BUILD_THRIFT_DIR}/, $(addsuffix .thrift, ${THRIFT_FILES})) 73 | BM_TENJIN_OUTPUT_THRIFT_SERVICES = $(addprefix ${BM_BUILD_THRIFT_DIR}/, $(addsuffix .thrift, ${THRIFT_FILES_WITH_SERVICES})) 74 | 75 | # Output of Tenjin are the following files: 76 | # p4c_bm/templates/src/*.c 77 | # p4c_bm/templates/src/*.h 78 | # p4c_bm/templates/inc/*.h 79 | # p4c_bm_templates/src/*.cpp 80 | # p4c_bm_templates/thrift/*.thrift 81 | # All files are output to ${BM_BUILD_DIR}/src/ 82 | BM_TENJIN_OUTPUT := ${BM_TENJIN_OUTPUT_C} ${BM_TENJIN_OUTPUT_H} ${BM_TENJIN_OUTPUT_CPP} ${BM_TENJIN_OUTPUT_THRIFT} ${BM_TENJIN_OUTPUT_PUBLIC_HEADERS} 83 | 84 | BM_TENJIN_OUTPUT_NEWEST := $(shell ls -t ${BM_TENJIN_OUTPUT} 2> /dev/null | head -1) 85 | BM_TENJIN_OUTPUT_OLDEST := $(shell ls -tr ${BM_TENJIN_OUTPUT} 2> /dev/null | head -1) 86 | # For a first-time build, above 2 variables will be empty. 87 | ifeq (${BM_TENJIN_OUTPUT_NEWEST},) 88 | BM_TENJIN_OUTPUT_NEWEST := ${BM_BUILD_SRC_DIR}/pd.c 89 | endif 90 | ifeq (${BM_TENJIN_OUTPUT_OLDEST},) 91 | BM_TENJIN_OUTPUT_OLDEST := bm_tenjin_output_oldest 92 | endif 93 | 94 | # Make the oldest Tenjin output depend on P4 program and input templates. 95 | ${BM_TENJIN_OUTPUT_OLDEST}: %: $(BM_TEMPLATES) ${P4_INPUT} $(wildcard ${P4_INCLUDES_DIR}/*.p4) $(wildcard ${P4_INCLUDES_DIR}/*.h) 96 | ${BM_SHELL} ${P4_INPUT} ${BM_PARAMS} ${TARGET_PARAMS} 97 | 98 | # Make all Tenjin output files depend on the oldest Tenjin output file. 99 | BM_TENJIN_DUMMY_TARGETS := $(filter-out ${BM_TENJIN_OUTPUT_OLDEST}, ${BM_TENJIN_OUTPUT}) 100 | ${BM_TENJIN_DUMMY_TARGETS} : ${BM_TENJIN_OUTPUT_OLDEST} 101 | 102 | # Every target that depends on the Tenjin output should just add BM_TENJIN_TARGET to its pre-requisite list. 103 | BM_TENJIN_TARGET := ${BM_TENJIN_OUTPUT_NEWEST} 104 | 105 | THRIFT_PD_BASENAMES = $(addsuffix _constants, ${THRIFT_FILES}) 106 | THRIFT_PD_BASENAMES += $(addsuffix _types, ${THRIFT_FILES}) 107 | THRIFT_PD_BASENAMES += ${THRIFT_SERVICES} 108 | 109 | BM_THRIFT_OUTPUT_PREREQ := $(addprefix ${BM_BUILD_SRC_DIR}/, $(addsuffix _types.h, ${THRIFT_FILES_WITH_SERVICES})) 110 | 111 | BM_THRIFT_OUTPUT_CPP := $(addprefix ${BM_BUILD_SRC_DIR}/, $(addsuffix .cpp, ${THRIFT_PD_BASENAMES})) 112 | BM_THRIFT_OUTPUT_H := $(addprefix ${BM_BUILD_SRC_DIR}/, $(addsuffix .h, ${THRIFT_PD_BASENAMES})) 113 | 114 | ${BM_THRIFT_OUTPUT_PREREQ}: ${BM_TENJIN_OUTPUT_THRIFT} ${BM_TENJIN_TARGET} 115 | $(foreach t,${BM_TENJIN_OUTPUT_THRIFT_SERVICES},thrift -r --gen cpp --out ${BM_BUILD_SRC_DIR} ${t} && ) true 116 | ${BM_THRIFT_OUTPUT_CPP} : ${BM_THRIFT_OUTPUT_PREREQ} 117 | 118 | ifdef COVERAGE 119 | COVERAGE_FLAGS := --coverage 120 | endif 121 | 122 | BM_OBJS_C := $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_TENJIN_OUTPUT_C})))) 123 | ${BM_OBJS_C} : ${BM_OBJ_DIR}/%.o : ${BM_BUILD_DIR}/src/%.c ${BM_TENJIN_TARGET} 124 | @echo " Compiling : bm::$(notdir $<)" 125 | $(VERBOSE)gcc -o $@ $(COVERAGE_FLAGS) $(DEBUG_FLAGS) $(GLOBAL_INCLUDES) $(GLOBAL_CFLAGS) -I $(PUBLIC_INC_PATH) -MD -c $< 126 | 127 | BM_OBJS_CPP := $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_TENJIN_OUTPUT_CPP})))) 128 | BM_OBJS_CPP += $(addsuffix .o, $(basename $(addprefix ${BM_OBJ_DIR}/, $(notdir ${BM_THRIFT_OUTPUT_CPP})))) 129 | ${BM_OBJS_CPP} : ${BM_OBJ_DIR}/%.o : ${BM_BUILD_SRC_DIR}/%.cpp ${BM_TENJIN_TARGET} ${BM_BUILD_SRC_DIR}/${P4_PREFIX}.cpp 130 | @echo " Compiling : bm::$(notdir $<)" 131 | $(VERBOSE)g++ -o $@ $(COVERAGE_FLAGS) $(DEBUG_FLAGS) $(GLOBAL_INCLUDES) -I ${PUBLIC_INC_PATH} -MD -c $< 132 | 133 | # Include the auto-generated .d dependency files. gcc/g++ generate the .d file 134 | # when -MD option is used. 135 | -include $(BM_OBJS_C:.o=.d) 136 | -include $(BM_OBJS_CPP:.o=.d) 137 | 138 | THRIFT_INPUT_FILES := ${BM_TENJIN_OUTPUT_THRIFT_SERVICES} 139 | THRIFT_DEP_FILES := ${BM_TENJIN_OUTPUT_THRIFT} 140 | THRIFT_SERVICE_NAMES := ${THRIFT_SERVICES} 141 | include ${MAKEFILES_DIR}/thrift-py.mk 142 | 143 | ${BM_LIB}: ${BM_OBJS_C} ${BM_OBJS_CPP} 144 | @echo " Creating : $(notdir $@)" 145 | $(VERBOSE)ar -rc $@ $^ 146 | 147 | .PHONY: bm.a 148 | --------------------------------------------------------------------------------