| @@ 403-439 (lines=37) @@ | ||
| 400 | All ports if :attr:`.Port.OFPP_ALL`. |
|
| 401 | queue_id (int): All queues if OFPQ_ALL (``0xfffffff``). |
|
| 402 | """ |
|
| 403 | super().__init__() |
|
| 404 | self.port_no = port_no |
|
| 405 | self.queue_id = queue_id |
|
| 406 | ||
| 407 | ||
| 408 | class TableStats(GenericStruct): |
|
| 409 | """Body of reply to OFPST_TABLE request.""" |
|
| 410 | ||
| 411 | table_id = UBInt8() |
|
| 412 | #: Align to 32-bits. |
|
| 413 | pad = Pad(3) |
|
| 414 | name = Char(length=OFP_MAX_TABLE_NAME_LEN) |
|
| 415 | wildcards = UBInt32(enum_ref=FlowWildCards) |
|
| 416 | max_entries = UBInt32() |
|
| 417 | active_count = UBInt32() |
|
| 418 | count_lookup = UBInt64() |
|
| 419 | count_matched = UBInt64() |
|
| 420 | ||
| 421 | def __init__(self, table_id=None, name=None, wildcards=None, |
|
| 422 | max_entries=None, active_count=None, count_lookup=None, |
|
| 423 | count_matched=None): |
|
| 424 | """Create a TableStats with the optional parameters below. |
|
| 425 | ||
| 426 | Args: |
|
| 427 | table_id (int): Identifier of table. Lower numbered tables are |
|
| 428 | consulted first. |
|
| 429 | name (str): Table name. |
|
| 430 | wildcards (:class:`~pyof.v0x01.common.flow_match.FlowWildCards`): |
|
| 431 | Bitmap of OFPFW_* wildcards that are supported by the table. |
|
| 432 | max_entries (int): Max number of entries supported. |
|
| 433 | active_count (int): Number of active entries. |
|
| 434 | count_lookup (int): Number of packets looked up in table. |
|
| 435 | count_matched (int): Number of packets that hit table. |
|
| 436 | """ |
|
| 437 | super().__init__() |
|
| 438 | self.table_id = table_id |
|
| 439 | self.name = name |
|
| 440 | self.wildcards = wildcards |
|
| 441 | self.max_entries = max_entries |
|
| 442 | self.active_count = active_count |
|
| @@ 36-76 (lines=41) @@ | ||
| 33 | ||
| 34 | # Classes |
|
| 35 | ||
| 36 | class SwitchFeatures(GenericMessage): |
|
| 37 | """Message sent by the switch device to the controller. |
|
| 38 | ||
| 39 | This message is the response for a features_request message, sent by the |
|
| 40 | controller to the switch device. The 'OFPT_FEATURES_REPLY' message inherits |
|
| 41 | from this class, despite the strange name. |
|
| 42 | """ |
|
| 43 | ||
| 44 | header = Header(message_type=Type.OFPT_FEATURES_REPLY) |
|
| 45 | datapath_id = DPID() |
|
| 46 | n_buffers = UBInt32() |
|
| 47 | n_tables = UBInt8() |
|
| 48 | #: Align to 64-bits. |
|
| 49 | pad = Pad(3) |
|
| 50 | # Features |
|
| 51 | capabilities = UBInt32(enum_ref=Capabilities) |
|
| 52 | actions = UBInt32(enum_ref=ActionType) |
|
| 53 | ports = ListOfPhyPorts() |
|
| 54 | ||
| 55 | def __init__(self, xid=None, datapath_id=None, n_buffers=None, |
|
| 56 | n_tables=None, capabilities=None, actions=None, ports=None): |
|
| 57 | """Create a SwitchFeatures with the optional parameters below. |
|
| 58 | ||
| 59 | Args: |
|
| 60 | xid (int): xid to be used on the message header. |
|
| 61 | datapath_id (:class:`str` or :class:`.DPID`): datapath unique ID. |
|
| 62 | The lower 48-bits are for MAC address, while |
|
| 63 | the upper 16-bits are implementer-defined. |
|
| 64 | n_buffers (int): UBInt32 max packets buffered at once. |
|
| 65 | n_tables (int): UBInt8 number of tables supported by datapath. |
|
| 66 | capabilities (int): UBInt32 bitmap of supported capabilities. |
|
| 67 | actions (int): UBInt32 Bitmap of supported "action_type"s. |
|
| 68 | ports (int): Port definitions. |
|
| 69 | """ |
|
| 70 | super().__init__(xid) |
|
| 71 | self.datapath_id = datapath_id |
|
| 72 | self.n_buffers = n_buffers |
|
| 73 | self.n_tables = n_tables |
|
| 74 | self.capabilities = capabilities |
|
| 75 | self.actions = actions |
|
| 76 | self.ports = [] if ports is None else ports |
|
| 77 | ||
| 78 | ||
| 79 | class FeaturesReply(SwitchFeatures): |
|
| @@ 18-55 (lines=38) @@ | ||
| 15 | # Classes |
|
| 16 | ||
| 17 | ||
| 18 | class PortMod(GenericMessage): |
|
| 19 | """Implement messages to modify the physical port behavior.""" |
|
| 20 | ||
| 21 | header = Header(message_type=Type.OFPT_PORT_MOD) |
|
| 22 | port_no = UBInt32() |
|
| 23 | pad = Pad(4) |
|
| 24 | hw_addr = HWAddress() |
|
| 25 | pad2 = Pad(2) |
|
| 26 | config = UBInt32(enum_ref=PortConfig) |
|
| 27 | mask = UBInt32(enum_ref=PortConfig) |
|
| 28 | advertise = UBInt32(enum_ref=PortFeatures) |
|
| 29 | #: Pad to 64-bits. |
|
| 30 | pad3 = Pad(4) |
|
| 31 | ||
| 32 | def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, |
|
| 33 | mask=None, advertise=None): |
|
| 34 | """Create a PortMod with the optional parameters below. |
|
| 35 | ||
| 36 | Args: |
|
| 37 | xid (int): OpenFlow xid to the header. |
|
| 38 | port_no (int): Physical port number. |
|
| 39 | hw_addr (HWAddress): The hardware address is not configurable. |
|
| 40 | This is used to sanity-check the request, |
|
| 41 | so it must be the same as returned in an ofp_phy_port struct. |
|
| 42 | config (~pyof.v0x04.common.port.PortConfig): |
|
| 43 | Bitmap of OFPPC_* flags |
|
| 44 | mask (~pyof.v0x04.common.port.PortConfig): |
|
| 45 | Bitmap of OFPPC_* flags to be changed |
|
| 46 | advertise (~pyof.v0x04.common.port.PortFeatures): |
|
| 47 | Bitmap of OFPPF_*. Zero all bits to prevent any action taking |
|
| 48 | place. |
|
| 49 | """ |
|
| 50 | super().__init__(xid) |
|
| 51 | self.port_no = port_no |
|
| 52 | self.hw_addr = hw_addr |
|
| 53 | self.config = config |
|
| 54 | self.mask = mask |
|
| 55 | self.advertise = advertise |
|
| 56 | ||
| @@ 18-52 (lines=35) @@ | ||
| 15 | # Classes |
|
| 16 | ||
| 17 | ||
| 18 | class PortMod(GenericMessage): |
|
| 19 | """Implement messages to modify the physical port behavior.""" |
|
| 20 | ||
| 21 | header = Header(message_type=Type.OFPT_PORT_MOD) |
|
| 22 | port_no = UBInt16() |
|
| 23 | hw_addr = HWAddress() |
|
| 24 | config = UBInt32(enum_ref=PortConfig) |
|
| 25 | mask = UBInt32(enum_ref=PortConfig) |
|
| 26 | advertise = UBInt32(enum_ref=PortFeatures) |
|
| 27 | #: Pad to 64-bits. |
|
| 28 | pad = Pad(4) |
|
| 29 | ||
| 30 | def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, |
|
| 31 | mask=None, advertise=None): |
|
| 32 | """Create a PortMod with the optional parameters below. |
|
| 33 | ||
| 34 | Args: |
|
| 35 | xid (int): OpenFlow xid to the header. |
|
| 36 | port_no (int): Physical port number. |
|
| 37 | hw_addr (HWAddress): The hardware address is not configurable. |
|
| 38 | This is used to sanity-check the request, |
|
| 39 | so it must be the same as returned in an ofp_phy_port struct. |
|
| 40 | config (~pyof.v0x01.common.phy_port.PortConfig): |
|
| 41 | Bitmap of OFPPC_* flags |
|
| 42 | mask (~pyof.v0x01.common.phy_port.PortConfig): |
|
| 43 | Bitmap of OFPPC_* flags to be changed |
|
| 44 | advertise (~pyof.v0x01.common.phy_port.PortFeatures): |
|
| 45 | Bitmap of "ofp_port_features"s |
|
| 46 | """ |
|
| 47 | super().__init__(xid) |
|
| 48 | self.port_no = port_no |
|
| 49 | self.hw_addr = hw_addr |
|
| 50 | self.config = config |
|
| 51 | self.mask = mask |
|
| 52 | self.advertise = advertise |
|
| 53 | ||
| @@ 36-80 (lines=45) @@ | ||
| 33 | ||
| 34 | # Classes |
|
| 35 | ||
| 36 | class SwitchFeatures(GenericMessage): |
|
| 37 | """Message sent by the switch device to the controller. |
|
| 38 | ||
| 39 | This message is the response for a features_request message, sent by the |
|
| 40 | controller to the switch device. The 'OFPT_FEATURES_REPLY' message inherits |
|
| 41 | from this class, despite the strange name. |
|
| 42 | """ |
|
| 43 | ||
| 44 | header = Header(message_type=Type.OFPT_FEATURES_REPLY) |
|
| 45 | datapath_id = DPID() |
|
| 46 | ||
| 47 | n_buffers = UBInt32() |
|
| 48 | ||
| 49 | n_tables = UBInt8() |
|
| 50 | auxiliary_id = UBInt8() |
|
| 51 | #: Align to 64-bits. |
|
| 52 | pad = Pad(2) |
|
| 53 | ||
| 54 | # Features |
|
| 55 | capabilities = UBInt32(enum_ref=Capabilities) |
|
| 56 | reserved = UBInt32() |
|
| 57 | ||
| 58 | def __init__(self, xid=None, datapath_id=None, n_buffers=None, |
|
| 59 | n_tables=None, auxiliary_id=None, capabilities=None, |
|
| 60 | reserved=None): |
|
| 61 | """Create a SwitchFeatures with the optional parameters below. |
|
| 62 | ||
| 63 | Args: |
|
| 64 | xid (int): xid to be used on the message header. |
|
| 65 | datapath_id (int): Datapath unique ID. |
|
| 66 | The lower 48-bits are for MAC address, while |
|
| 67 | the upper 16-bits are implementer-defined. |
|
| 68 | n_buffers (int): Max packets buffered at once. |
|
| 69 | n_tables (int): Number of tables supported by datapath. |
|
| 70 | auxiliary_id (int): Identify auxiliary connections. |
|
| 71 | capabilities (int): bitmap of supported capabilities. |
|
| 72 | reserved (int): Reserved. |
|
| 73 | """ |
|
| 74 | super().__init__(xid) |
|
| 75 | self.datapath_id = datapath_id |
|
| 76 | self.n_buffers = n_buffers |
|
| 77 | self.n_tables = n_tables |
|
| 78 | self.auxiliary_id = auxiliary_id |
|
| 79 | self.capabilities = capabilities |
|
| 80 | self.reserved = reserved |
|
| 81 | ||
| 82 | ||
| 83 | class FeaturesReply(SwitchFeatures): |
|
| @@ 156-203 (lines=48) @@ | ||
| 153 | return BinaryData(b'') |
|
| 154 | ||
| 155 | ||
| 156 | class AggregateStatsRequest(GenericStruct): |
|
| 157 | """Body for ofp_stats_request of type OFPST_AGGREGATE.""" |
|
| 158 | ||
| 159 | #: ID of table to read (from ofp_table_stats) OFPTT_ALL for all tables. |
|
| 160 | table_id = UBInt8() |
|
| 161 | #: Align to 32 bits. |
|
| 162 | pad = Pad(3) |
|
| 163 | #: Require matching entries to include this as an output port. A value of |
|
| 164 | #: OFPP_ANY indicates no restriction. |
|
| 165 | out_port = UBInt32() |
|
| 166 | #: Require matching entries to include this as an output group. A value of |
|
| 167 | #: OFPG_ANY indicates no restriction. |
|
| 168 | out_group = UBInt32() |
|
| 169 | #: Align to 64 bits |
|
| 170 | pad2 = Pad(4) |
|
| 171 | #: Require matching entries to contain this cookie value |
|
| 172 | cookie = UBInt64() |
|
| 173 | #: Mask used to restrict the cookie bits that must match. A value of 0 |
|
| 174 | #: indicates no restriction. |
|
| 175 | cookie_mask = UBInt64() |
|
| 176 | #: Fields to match. Variable size. |
|
| 177 | match = Match() |
|
| 178 | ||
| 179 | def __init__(self, table_id=Table.OFPTT_ALL, out_port=PortNo.OFPP_ANY, |
|
| 180 | out_group=Group.OFPG_ANY, cookie=0, cookie_mask=0, |
|
| 181 | match=None): |
|
| 182 | """Create a AggregateStatsRequest with the optional parameters below. |
|
| 183 | ||
| 184 | Args: |
|
| 185 | table_id (int): ID of table to read (from ofp_table_stats) |
|
| 186 | OFPTT_ALL for all tables. |
|
| 187 | out_port (int): Require matching entries to include this as an |
|
| 188 | output port. A value of OFPP_ANY indicates no restriction. |
|
| 189 | out_group (int): Require matching entries to include this as an |
|
| 190 | output group. A value of OFPG_ANY indicates no restriction. |
|
| 191 | cookie (int): Require matching entries to contain this cookie value |
|
| 192 | cookie_mask (int): Mask used to restrict the cookie bits that must |
|
| 193 | match. A value of 0 indicates no restriction. |
|
| 194 | match (~pyof.v0x04.common.flow_match.Match): |
|
| 195 | Fields to match. Variable size |
|
| 196 | """ |
|
| 197 | super().__init__() |
|
| 198 | self.table_id = table_id |
|
| 199 | self.out_port = out_port |
|
| 200 | self.out_group = out_group |
|
| 201 | self.cookie = cookie |
|
| 202 | self.cookie_mask = cookie_mask |
|
| 203 | self.match = Match() if match is None else match |
|
| 204 | ||
| 205 | ||
| 206 | class FlowStatsRequest(GenericStruct): |
|
| @@ 206-244 (lines=39) @@ | ||
| 203 | self.match = Match() if match is None else match |
|
| 204 | ||
| 205 | ||
| 206 | class FlowStatsRequest(GenericStruct): |
|
| 207 | """Body for ofp_stats_request of type OFPST_FLOW.""" |
|
| 208 | ||
| 209 | table_id = UBInt8() |
|
| 210 | #: Align to 32 bits. |
|
| 211 | pad = Pad(3) |
|
| 212 | out_port = UBInt32() |
|
| 213 | out_group = UBInt32() |
|
| 214 | pad2 = Pad(4) |
|
| 215 | cookie = UBInt64() |
|
| 216 | cookie_mask = UBInt64() |
|
| 217 | match = Match() |
|
| 218 | ||
| 219 | def __init__(self, table_id=Table.OFPTT_ALL, out_port=PortNo.OFPP_ANY, |
|
| 220 | out_group=Group.OFPG_ANY, cookie=0, cookie_mask=0, |
|
| 221 | match=None): |
|
| 222 | """Create a FlowStatsRequest with the optional parameters below. |
|
| 223 | ||
| 224 | Args: |
|
| 225 | table_id (int): ID of table to read (from pyof_table_stats) |
|
| 226 | 0xff for all tables or 0xfe for emergency. |
|
| 227 | out_port (:class:`int`, :class:`~pyof.v0x04.common.port.PortNo`): |
|
| 228 | Require matching entries to include this as an output port. |
|
| 229 | A value of :attr:`.PortNo.OFPP_ANY` indicates no restriction. |
|
| 230 | out_group: Require matching entries to include this as an output |
|
| 231 | group. A value of :attr:`Group.OFPG_ANY` indicates no |
|
| 232 | restriction. |
|
| 233 | cookie: Requires matching entries to contain this cookie value |
|
| 234 | cookie_mask: Mask used to restrict the cookie bits that must match. |
|
| 235 | A value of 0 indicates no restriction. |
|
| 236 | match (~pyof.v0x04.common.flow_match.Match): Fields to match. |
|
| 237 | """ |
|
| 238 | super().__init__() |
|
| 239 | self.table_id = table_id |
|
| 240 | self.out_port = out_port |
|
| 241 | self.out_group = out_group |
|
| 242 | self.cookie = cookie |
|
| 243 | self.cookie_mask = cookie_mask |
|
| 244 | self.match = Match() if match is None else match |
|
| 245 | ||
| 246 | ||
| 247 | class PortStatsRequest(GenericStruct): |
|
| @@ 34-100 (lines=67) @@ | ||
| 31 | # Classes |
|
| 32 | ||
| 33 | ||
| 34 | class PacketIn(GenericMessage): |
|
| 35 | """Packet received on port (datapath -> controller).""" |
|
| 36 | ||
| 37 | #: :class:`~pyof.v0x04.common.header.Header`: OpenFlow Header |
|
| 38 | header = Header(message_type=Type.OFPT_PACKET_IN) |
|
| 39 | #: ID assigned by datapath. |
|
| 40 | buffer_id = UBInt32() |
|
| 41 | #: Full length of frame. |
|
| 42 | total_len = UBInt16() |
|
| 43 | #: Reason packet is being sent (one of OFPR_*), |
|
| 44 | reason = UBInt8(enum_ref=PacketInReason) |
|
| 45 | #: ID of the table that was looked up. |
|
| 46 | table_id = UBInt8() |
|
| 47 | #: Cookie of the flow entry that was looked up. |
|
| 48 | cookie = UBInt64() |
|
| 49 | #: Packet metadata. Variable size. |
|
| 50 | match = Match() |
|
| 51 | #: Align to 64 bit + 16 bit |
|
| 52 | pad = Pad(2) |
|
| 53 | #: Ethernet frame whose length is inferred from header.length. |
|
| 54 | #: The padding bytes preceding the Ethernet frame ensure that the IP |
|
| 55 | #: header (if any) following the Ethernet header is 32-bit aligned. |
|
| 56 | data = BinaryData() |
|
| 57 | ||
| 58 | def __init__(self, xid=None, buffer_id=None, total_len=None, reason=None, |
|
| 59 | table_id=None, cookie=None, match=None, data=b''): |
|
| 60 | """Assign parameters to object attributes. |
|
| 61 | ||
| 62 | Args: |
|
| 63 | xid (int): Header's xid. |
|
| 64 | buffer_id (int): ID assigned by datapath. |
|
| 65 | total_len (int): Full length of frame. |
|
| 66 | reason (~pyof.v0x04.asynchronous.packet_in.PacketInReason): |
|
| 67 | The reason why the packet is being sent |
|
| 68 | table_id (int): ID of the table that was looked up |
|
| 69 | cookie (int): Cookie of the flow entry that was looked up |
|
| 70 | match (:class:`~pyof.v0x04.common.flow_match.Match`): |
|
| 71 | Packet metadata with variable size. |
|
| 72 | data (bytes): Ethernet frame, halfway through 32-bit word, so the |
|
| 73 | IP header is 32-bit aligned. The amount of data is inferred |
|
| 74 | from the length field in the header. Because of padding, |
|
| 75 | offsetof(struct ofp_packet_in, data) == |
|
| 76 | sizeof(struct ofp_packet_in) - 2. |
|
| 77 | """ |
|
| 78 | super().__init__(xid) |
|
| 79 | self.buffer_id = buffer_id |
|
| 80 | self.total_len = total_len |
|
| 81 | self.reason = reason |
|
| 82 | self.table_id = table_id |
|
| 83 | self.cookie = cookie |
|
| 84 | self.match = match |
|
| 85 | self.data = data |
|
| 86 | ||
| 87 | @property |
|
| 88 | def in_port(self): |
|
| 89 | """Retrieve the 'in_port' that generated the PacketIn. |
|
| 90 | ||
| 91 | This method will look for the OXM_TLV with type OFPXMT_OFB_IN_PORT on |
|
| 92 | the `oxm_match_fields` field from `match` field and return its value, |
|
| 93 | if the OXM exists. |
|
| 94 | ||
| 95 | Returns: |
|
| 96 | The integer number of the 'in_port' that generated the PacketIn if |
|
| 97 | it exists. Otherwise return None. |
|
| 98 | ||
| 99 | """ |
|
| 100 | return self.match.get_field(OxmOfbMatchField.OFPXMT_OFB_IN_PORT) |
|
| 101 | ||