Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 1 | ## List of mixed data types |
| 2 | # |
| 3 | # This is a list of data types which require special treatment |
| 4 | # because the underlying datatype has changed between versions. |
| 5 | # The main example is port which went from 16 to 32 bits. We |
| 6 | # define per-version accessors for these types and those are |
| 7 | # used in place of the normal ones. |
| 8 | # |
| 9 | # The wire protocol number is used to identify versions. For now, |
| 10 | # the value is the name of the type to use for that version |
| 11 | # |
| 12 | # This is the map between the external type (like of_port_no_t) |
| 13 | # which is used by customers of this code and the internal |
| 14 | # datatypes (like uint16_t) that appear on the wire for a |
| 15 | # particular version. |
| 16 | # |
| 17 | from collections import namedtuple |
| 18 | import logging |
| 19 | |
| 20 | import loxi_front_end.frontend_ir as fe |
| 21 | import loxi_ir.ir |
| 22 | |
| 23 | ofp_constants = dict( |
| 24 | OF_MAX_TABLE_NAME_LEN = 32, |
| 25 | OF_MAX_PORT_NAME_LEN = 16, |
| 26 | OF_ETH_ALEN = 6, |
| 27 | OF_DESC_STR_LEN = 256, |
Praseed Balakrishnan | 7f71878 | 2014-09-18 17:02:48 -0700 | [diff] [blame] | 28 | OF_SERIAL_NUM_LEN = 32, |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 29 | OF_APP_CODE_LEN = 15, |
| 30 | OF_CONTROLLER_URI_LEN = 32 |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 31 | ) |
| 32 | |
| 33 | |
| 34 | of_mixed_types = dict( |
| 35 | of_port_no_t = { |
| 36 | 1: "uint16_t", |
| 37 | 2: "uint32_t", |
| 38 | 3: "uint32_t", |
| 39 | 4: "uint32_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 40 | 5: "uint32_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 41 | 6: "uint32_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 42 | "short_name":"port_no" |
| 43 | }, |
| 44 | of_port_desc_t = { |
| 45 | 1: "of_port_desc_t", |
| 46 | 2: "of_port_desc_t", |
| 47 | 3: "of_port_desc_t", |
| 48 | 4: "of_port_desc_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 49 | 5: "of_port_desc_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 50 | 6: "of_port_desc_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 51 | "short_name":"port_desc" |
| 52 | }, |
| 53 | of_bsn_vport_t = { |
| 54 | 1: "of_bsn_vport_t", |
| 55 | 2: "of_bsn_vport_t", |
| 56 | 3: "of_bsn_vport_t", |
| 57 | 4: "of_bsn_vport_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 58 | 5: "of_bsn_vport_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 59 | 6: "of_bsn_vport_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 60 | "short_name":"bsn_vport" |
| 61 | }, |
| 62 | of_fm_cmd_t = { # Flow mod command went from u16 to u8 |
| 63 | 1: "uint16_t", |
| 64 | 2: "uint8_t", |
| 65 | 3: "uint8_t", |
| 66 | 4: "uint8_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 67 | 5: "uint8_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 68 | 6: "uint8_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 69 | "short_name":"fm_cmd" |
| 70 | }, |
| 71 | of_wc_bmap_t = { # Wildcard bitmap |
| 72 | 1: "uint32_t", |
| 73 | 2: "uint32_t", |
| 74 | 3: "uint64_t", |
| 75 | 4: "uint64_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 76 | 5: "uint64_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 77 | 6: "uint64_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 78 | "short_name":"wc_bmap" |
| 79 | }, |
| 80 | of_match_bmap_t = { # Match bitmap |
| 81 | 1: "uint32_t", |
| 82 | 2: "uint32_t", |
| 83 | 3: "uint64_t", |
| 84 | 4: "uint64_t", |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 85 | 5: "uint64_t", |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 86 | 6: "uint64_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 87 | "short_name":"match_bmap" |
| 88 | }, |
| 89 | of_match_t = { # Match object |
| 90 | 1: "of_match_v1_t", |
| 91 | 2: "of_match_v2_t", |
| 92 | 3: "of_match_v3_t", |
| 93 | 4: "of_match_v3_t", # Currently uses same match as 1.2 (v3). |
alshabib | 9f50e48 | 2014-08-23 17:10:57 -0500 | [diff] [blame] | 94 | 5: "of_match_v3_t", # Currently uses same match as 1.2 (v3). |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 95 | 6: "of_match_v3_t", |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 96 | "short_name":"match" |
| 97 | }, |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 98 | of_stat_t = { #Statistics object |
| 99 | 6: "of_stat_v6_t", |
| 100 | "short_name":"stat" |
| 101 | }, |
| 102 | of_time_t = { # time object |
| 103 | 6: "of_time_t", |
| 104 | "short_name":"time" |
| 105 | } |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 106 | ) |
| 107 | |
| 108 | ## basic lengths |
| 109 | of_base_lengths = dict( |
| 110 | char = (1, True), |
| 111 | uint8_t = (1, True), |
| 112 | uint16_t = (2, True), |
| 113 | uint32_t = (4, True), |
| 114 | uint64_t = (8, True), |
| 115 | of_mac_addr_t = (6, True), |
| 116 | of_ipv4_t = (4, True), |
| 117 | of_ipv6_t = (16, True), |
| 118 | of_port_name_t = (ofp_constants["OF_MAX_PORT_NAME_LEN"], True), |
| 119 | of_table_name_t = (ofp_constants["OF_MAX_TABLE_NAME_LEN"], True), |
| 120 | of_desc_str_t = (ofp_constants["OF_DESC_STR_LEN"], True), |
| 121 | of_serial_num_t = (ofp_constants["OF_SERIAL_NUM_LEN"], True), |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 122 | of_controller_uri_t = (ofp_constants["OF_CONTROLLER_URI_LEN"], True), |
Rich Lane | f8a3d00 | 2014-03-19 13:33:52 -0700 | [diff] [blame] | 123 | of_str64_t = (64, True), |
Brian O'Connor | 58a73e3 | 2015-05-28 11:51:27 -0700 | [diff] [blame] | 124 | of_str32_t = (32, True), |
| 125 | of_str6_t = (6, True), |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 126 | of_match_v1_t = (40, True), |
| 127 | of_match_v2_t = (88, True), |
| 128 | of_match_v3_t = (8, False), |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 129 | of_stat_v6_t = (8, False), |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 130 | of_octets_t = (0, False), |
| 131 | of_bitmap_128_t = (16, True), |
Rich Lane | 5183398 | 2013-12-03 13:02:45 -0800 | [diff] [blame] | 132 | of_checksum_128_t = (16, True), |
Praseed Balakrishnan | 7f71878 | 2014-09-18 17:02:48 -0700 | [diff] [blame] | 133 | of_app_code_t = (15,True), |
Praseed Balakrishnan | 2ed6da0 | 2014-09-18 17:02:48 -0700 | [diff] [blame] | 134 | of_sig_id_t = (6, True), |
Jimmy Jin | 646d122 | 2016-05-13 10:47:24 -0700 | [diff] [blame] | 135 | of_bitmap_256_t = (32, True), |
Rich Lane | 931eab3 | 2014-11-13 15:42:29 -0800 | [diff] [blame] | 136 | of_bitmap_512_t = (64, True), |
Yafit Hadar | f8caac0 | 2015-08-25 10:21:44 +0300 | [diff] [blame] | 137 | of_odu_sig_id_t = (16, True), |
| 138 | of_och_sig_id_t = (6, True), |
Murat Parlakisik | f95672c | 2016-12-05 00:53:17 -0800 | [diff] [blame] | 139 | of_time_t = (16, True) |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 140 | ) |
| 141 | |
| 142 | def type_dec_to_count_base(m_type): |
| 143 | """ |
| 144 | Resolve a type declaration like uint8_t[4] to a count (4) and base_type |
| 145 | (uint8_t) |
| 146 | |
| 147 | @param m_type The string type declaration to process |
| 148 | """ |
| 149 | count = 1 |
| 150 | chk_ar = m_type.split('[') |
| 151 | if len(chk_ar) > 1: |
| 152 | count_str = chk_ar[1].split(']')[0] |
| 153 | if count_str in ofp_constants: |
| 154 | count = ofp_constants[count_str] |
| 155 | else: |
| 156 | count = int(count_str) |
| 157 | base_type = chk_ar[0] |
| 158 | else: |
| 159 | base_type = m_type |
| 160 | return count, base_type |
| 161 | |
| 162 | |
| 163 | LengthInfo = namedtuple("LengthInfo", ("offset", "base_length", "is_fixed_length")) |
| 164 | |
| 165 | def calc_lengths(version, fe_class, existing_classes, existing_enums): |
| 166 | offset_fixed = True |
| 167 | offset = 0 |
| 168 | |
| 169 | member_infos = {} |
| 170 | for member in fe_class.members: |
| 171 | member_offset = offset if offset_fixed else None |
| 172 | |
| 173 | if isinstance(member, fe.OFPadMember): |
| 174 | member_base_length = member.length |
| 175 | member_fixed_length = True |
| 176 | else: |
| 177 | m_type = member.oftype |
| 178 | name = member.name |
| 179 | |
| 180 | member_base_length = 0 |
| 181 | if m_type.find("list(") == 0: |
| 182 | member_fixed_length = False |
| 183 | elif m_type.find("struct") == 0: |
| 184 | raise Exception("Error: recursive struct found: {}, {}" |
| 185 | .format(fe_class.name, name)) |
| 186 | elif m_type == "octets": |
| 187 | member_fixed_length = False |
| 188 | else: |
| 189 | member_base_length, member_fixed_length = member_length(version, fe_class, member, existing_classes, existing_enums) |
| 190 | |
| 191 | if not member_fixed_length: |
| 192 | offset_fixed = False |
| 193 | |
| 194 | member_infos[member] = LengthInfo(member_offset, member_base_length, |
| 195 | member_fixed_length) |
| 196 | offset += member_base_length |
| 197 | |
| 198 | base_length = offset |
| 199 | fixed_length = offset_fixed if not fe_class.virtual else False |
| 200 | return (base_length, fixed_length, member_infos) |
| 201 | |
| 202 | def member_length(version, fe_class, fe_member, existing_classes, existing_enums): |
| 203 | """ |
| 204 | return the length of an ir member. |
| 205 | |
| 206 | @return tuple (base_length, length_fixed) |
| 207 | """ |
| 208 | count, base_type = type_dec_to_count_base(fe_member.oftype) |
| 209 | |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 210 | if base_type in of_mixed_types: |
| 211 | base_type = of_mixed_types[base_type][version.wire_version] |
| 212 | |
| 213 | base_class = base_type[:-2] |
| 214 | if base_class in existing_classes: |
| 215 | member_ir_class = existing_classes[base_class] |
| 216 | bytes = member_ir_class.base_length |
| 217 | length_fixed = member_ir_class.is_fixed_length |
Rich Lane | 824c088 | 2014-10-16 14:26:53 -0700 | [diff] [blame] | 218 | if member_ir_class.has_external_alignment: |
| 219 | bytes = (bytes + 7) & ~7 |
Andreas Wundsam | d30c107 | 2013-11-15 13:36:57 -0800 | [diff] [blame] | 220 | else: |
| 221 | if base_type in existing_enums: |
| 222 | enum = existing_enums[base_type] |
| 223 | base_type = enum.wire_type |
| 224 | |
| 225 | if base_type in of_base_lengths: |
| 226 | bytes, length_fixed = of_base_lengths[base_type] |
| 227 | else: |
| 228 | raise Exception("Unknown type for {}.{}: {}".format(fe_class.name, fe_member.name, base_type)) |
| 229 | |
| 230 | return (count * bytes), length_fixed |