1# Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation.
2# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
3# Copyright (C) 2012 Simon Horman <horms ad verge net au>
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
14# implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18import struct
19
20from ryu import exception
21from ryu.lib import mac
22from ryu.lib.pack_utils import msg_pack_into
23from ryu.ofproto import ether
24from ryu.ofproto import ofproto_parser
25from ryu.ofproto import ofproto_v1_0
26from ryu.ofproto import inet
27
28
29import logging
30LOG = logging.getLogger('ryu.ofproto.nx_match')
31
32
33UINT64_MAX = (1 << 64) - 1
34UINT32_MAX = (1 << 32) - 1
35UINT16_MAX = (1 << 16) - 1
36
37FWW_IN_PORT = 1 << 0
38FWW_DL_TYPE = 1 << 4
39FWW_NW_PROTO = 1 << 5
40# No corresponding OFPFW_* bits
41FWW_NW_DSCP = 1 << 1
42FWW_NW_ECN = 1 << 2
43FWW_ARP_SHA = 1 << 3
44FWW_ARP_THA = 1 << 6
45FWW_IPV6_LABEL = 1 << 7
46FWW_NW_TTL = 1 << 8
47FWW_ALL = (1 << 13) - 1
48
49FLOW_NW_FRAG_ANY = 1 << 0
50FLOW_NW_FRAG_LATER = 1 << 1
51FLOW_NW_FRAG_MASK = FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER
52
53IP_ECN_MASK = 0x03
54IP_DSCP_MASK = 0xfc
55
56MF_PACK_STRING_BE64 = '!Q'
57MF_PACK_STRING_BE32 = '!I'
58MF_PACK_STRING_BE16 = '!H'
59MF_PACK_STRING_8 = '!B'
60MF_PACK_STRING_MAC = '!6s'
61MF_PACK_STRING_IPV6 = '!8H'
62
63_MF_FIELDS = {}
64
65FLOW_N_REGS = 8  # ovs 1.5
66
67
68class Flow(ofproto_parser.StringifyMixin):
69    def __init__(self):
70        self.in_port = 0
71        self.dl_vlan = 0
72        self.dl_vlan_pcp = 0
73        self.dl_src = mac.DONTCARE
74        self.dl_dst = mac.DONTCARE
75        self.dl_type = 0
76        self.tp_dst = 0
77        self.tp_src = 0
78        self.nw_tos = 0
79        self.vlan_tci = 0
80        self.nw_ttl = 0
81        self.nw_proto = 0
82        self.arp_sha = 0
83        self.arp_tha = 0
84        self.nw_src = 0
85        self.nw_dst = 0
86        self.tun_id = 0
87        self.arp_spa = 0
88        self.arp_tpa = 0
89        self.ipv6_src = []
90        self.ipv6_dst = []
91        self.nd_target = []
92        self.nw_frag = 0
93        self.regs = [0] * FLOW_N_REGS
94        self.ipv6_label = 0
95        self.pkt_mark = 0
96        self.tcp_flags = 0
97
98
99class FlowWildcards(ofproto_parser.StringifyMixin):
100    def __init__(self):
101        self.dl_src_mask = 0
102        self.dl_dst_mask = 0
103        self.tp_src_mask = 0
104        self.tp_dst_mask = 0
105        self.nw_src_mask = 0
106        self.nw_dst_mask = 0
107        self.tun_id_mask = 0
108        self.arp_spa_mask = 0
109        self.arp_tpa_mask = 0
110        self.vlan_tci_mask = 0
111        self.ipv6_src_mask = []
112        self.ipv6_dst_mask = []
113        self.nd_target_mask = []
114        self.nw_frag_mask = 0
115        self.regs_bits = 0
116        self.regs_mask = [0] * FLOW_N_REGS
117        self.wildcards = ofproto_v1_0.OFPFW_ALL
118        self.pkt_mark_mask = 0
119        self.tcp_flags_mask = 0
120
121
122class ClsRule(ofproto_parser.StringifyMixin):
123    """describe a matching rule for OF 1.0 OFPMatch (and NX).
124    """
125
126    def __init__(self, **kwargs):
127        self.wc = FlowWildcards()
128        self.flow = Flow()
129
130        for key, value in kwargs.items():
131            if key[:3] == 'reg':
132                register = int(key[3:] or -1)
133                self.set_reg(register, value)
134                continue
135
136            setter = getattr(self, 'set_' + key, None)
137            if not setter:
138                LOG.error('Invalid kwarg specified to ClsRule (%s)', key)
139                continue
140
141            if not isinstance(value, (tuple, list)):
142                value = (value, )
143
144            setter(*value)
145
146    def set_in_port(self, port):
147        self.wc.wildcards &= ~FWW_IN_PORT
148        self.flow.in_port = port
149
150    def set_dl_vlan(self, dl_vlan):
151        self.wc.wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN
152        self.flow.dl_vlan = dl_vlan
153
154    def set_dl_vlan_pcp(self, dl_vlan_pcp):
155        self.wc.wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN_PCP
156        self.flow.dl_vlan_pcp = dl_vlan_pcp
157
158    def set_dl_dst(self, dl_dst):
159        self.flow.dl_dst = dl_dst
160
161    def set_dl_dst_masked(self, dl_dst, mask):
162        self.wc.dl_dst_mask = mask
163        # bit-wise and of the corresponding elements of dl_dst and mask
164        self.flow.dl_dst = mac.haddr_bitand(dl_dst, mask)
165
166    def set_dl_src(self, dl_src):
167        self.flow.dl_src = dl_src
168
169    def set_dl_src_masked(self, dl_src, mask):
170        self.wc.dl_src_mask = mask
171        self.flow.dl_src = mac.haddr_bitand(dl_src, mask)
172
173    def set_dl_type(self, dl_type):
174        self.wc.wildcards &= ~FWW_DL_TYPE
175        self.flow.dl_type = dl_type
176
177    def set_dl_tci(self, tci):
178        self.set_dl_tci_masked(tci, UINT16_MAX)
179
180    def set_dl_tci_masked(self, tci, mask):
181        self.wc.vlan_tci_mask = mask
182        self.flow.vlan_tci = tci
183
184    def set_tp_src(self, tp_src):
185        self.set_tp_src_masked(tp_src, UINT16_MAX)
186
187    def set_tp_src_masked(self, tp_src, mask):
188        self.wc.tp_src_mask = mask
189        self.flow.tp_src = tp_src & mask
190
191    def set_tp_dst(self, tp_dst):
192        self.set_tp_dst_masked(tp_dst, UINT16_MAX)
193
194    def set_tp_dst_masked(self, tp_dst, mask):
195        self.wc.tp_dst_mask = mask
196        self.flow.tp_dst = tp_dst & mask
197
198    def set_nw_proto(self, nw_proto):
199        self.wc.wildcards &= ~FWW_NW_PROTO
200        self.flow.nw_proto = nw_proto
201
202    def set_nw_src(self, nw_src):
203        self.set_nw_src_masked(nw_src, UINT32_MAX)
204
205    def set_nw_src_masked(self, nw_src, mask):
206        self.flow.nw_src = nw_src
207        self.wc.nw_src_mask = mask
208
209    def set_nw_dst(self, nw_dst):
210        self.set_nw_dst_masked(nw_dst, UINT32_MAX)
211
212    def set_nw_dst_masked(self, nw_dst, mask):
213        self.flow.nw_dst = nw_dst
214        self.wc.nw_dst_mask = mask
215
216    def set_nw_dscp(self, nw_dscp):
217        self.wc.wildcards &= ~FWW_NW_DSCP
218        self.flow.nw_tos &= ~IP_DSCP_MASK
219        self.flow.nw_tos |= nw_dscp & IP_DSCP_MASK
220
221    def set_icmp_type(self, icmp_type):
222        self.set_tp_src(icmp_type)
223
224    def set_icmp_code(self, icmp_code):
225        self.set_tp_dst(icmp_code)
226
227    def set_tun_id(self, tun_id):
228        self.set_tun_id_masked(tun_id, UINT64_MAX)
229
230    def set_tun_id_masked(self, tun_id, mask):
231        self.wc.tun_id_mask = mask
232        self.flow.tun_id = tun_id & mask
233
234    def set_nw_ecn(self, nw_ecn):
235        self.wc.wildcards &= ~FWW_NW_ECN
236        self.flow.nw_tos &= ~IP_ECN_MASK
237        self.flow.nw_tos |= nw_ecn & IP_ECN_MASK
238
239    def set_nw_ttl(self, nw_ttl):
240        self.wc.wildcards &= ~FWW_NW_TTL
241        self.flow.nw_ttl = nw_ttl
242
243    def set_nw_frag(self, nw_frag):
244        self.wc.nw_frag_mask |= FLOW_NW_FRAG_MASK
245        self.flow.nw_frag = nw_frag
246
247    def set_nw_frag_masked(self, nw_frag, mask):
248        self.wc.nw_frag_mask = mask
249        self.flow.nw_frag = nw_frag & mask
250
251    def set_arp_spa(self, spa):
252        self.set_arp_spa_masked(spa, UINT32_MAX)
253
254    def set_arp_spa_masked(self, spa, mask):
255        self.flow.arp_spa = spa
256        self.wc.arp_spa_mask = mask
257
258    def set_arp_tpa(self, tpa):
259        self.set_arp_tpa_masked(tpa, UINT32_MAX)
260
261    def set_arp_tpa_masked(self, tpa, mask):
262        self.flow.arp_tpa = tpa
263        self.wc.arp_tpa_mask = mask
264
265    def set_arp_sha(self, sha):
266        self.wc.wildcards &= ~FWW_ARP_SHA
267        self.flow.arp_sha = sha
268
269    def set_arp_tha(self, tha):
270        self.wc.wildcards &= ~FWW_ARP_THA
271        self.flow.arp_tha = tha
272
273    def set_icmpv6_type(self, icmp_type):
274        self.set_tp_src(icmp_type)
275
276    def set_icmpv6_code(self, icmp_code):
277        self.set_tp_dst(icmp_code)
278
279    def set_ipv6_label(self, label):
280        self.wc.wildcards &= ~FWW_IPV6_LABEL
281        self.flow.ipv6_label = label
282
283    def set_ipv6_src_masked(self, src, mask):
284        self.wc.ipv6_src_mask = mask
285        self.flow.ipv6_src = [x & y for (x, y) in zip(src, mask)]
286
287    def set_ipv6_src(self, src):
288        self.flow.ipv6_src = src
289
290    def set_ipv6_dst_masked(self, dst, mask):
291        self.wc.ipv6_dst_mask = mask
292        self.flow.ipv6_dst = [x & y for (x, y) in zip(dst, mask)]
293
294    def set_ipv6_dst(self, dst):
295        self.flow.ipv6_dst = dst
296
297    def set_nd_target_masked(self, target, mask):
298        self.wc.nd_target_mask = mask
299        self.flow.nd_target = [x & y for (x, y) in
300                               zip(target, mask)]
301
302    def set_nd_target(self, target):
303        self.flow.nd_target = target
304
305    def set_reg(self, reg_idx, value):
306        self.set_reg_masked(reg_idx, value, 0)
307
308    def set_reg_masked(self, reg_idx, value, mask):
309        self.wc.regs_mask[reg_idx] = mask
310        self.flow.regs[reg_idx] = value
311        self.wc.regs_bits |= (1 << reg_idx)
312
313    def set_pkt_mark_masked(self, pkt_mark, mask):
314        self.flow.pkt_mark = pkt_mark
315        self.wc.pkt_mark_mask = mask
316
317    def set_tcp_flags(self, tcp_flags, mask):
318        self.flow.tcp_flags = tcp_flags
319        self.wc.tcp_flags_mask = mask
320
321    def flow_format(self):
322        # Tunnel ID is only supported by NXM
323        if self.wc.tun_id_mask != 0:
324            return ofproto_v1_0.NXFF_NXM
325
326        # Masking DL_DST is only supported by NXM
327        if self.wc.dl_dst_mask:
328            return ofproto_v1_0.NXFF_NXM
329
330        # Masking DL_SRC is only supported by NXM
331        if self.wc.dl_src_mask:
332            return ofproto_v1_0.NXFF_NXM
333
334        # ECN is only supported by NXM
335        if not self.wc.wildcards & FWW_NW_ECN:
336            return ofproto_v1_0.NXFF_NXM
337
338        if self.wc.regs_bits > 0:
339            return ofproto_v1_0.NXFF_NXM
340
341        if self.flow.tcp_flags > 0:
342            return ofproto_v1_0.NXFF_NXM
343
344        return ofproto_v1_0.NXFF_OPENFLOW10
345
346    def match_tuple(self):
347        """return a tuple which can be used as *args for
348        ofproto_v1_0_parser.OFPMatch.__init__().
349        see Datapath.send_flow_mod.
350        """
351        assert self.flow_format() == ofproto_v1_0.NXFF_OPENFLOW10
352        wildcards = ofproto_v1_0.OFPFW_ALL
353
354        if not self.wc.wildcards & FWW_IN_PORT:
355            wildcards &= ~ofproto_v1_0.OFPFW_IN_PORT
356
357        if self.flow.dl_src != mac.DONTCARE:
358            wildcards &= ~ofproto_v1_0.OFPFW_DL_SRC
359
360        if self.flow.dl_dst != mac.DONTCARE:
361            wildcards &= ~ofproto_v1_0.OFPFW_DL_DST
362
363        if not self.wc.wildcards & FWW_DL_TYPE:
364            wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
365
366        if self.flow.dl_vlan != 0:
367            wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN
368
369        if self.flow.dl_vlan_pcp != 0:
370            wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN_PCP
371
372        if self.flow.nw_tos != 0:
373            wildcards &= ~ofproto_v1_0.OFPFW_NW_TOS
374
375        if self.flow.nw_proto != 0:
376            wildcards &= ~ofproto_v1_0.OFPFW_NW_PROTO
377
378        if self.wc.nw_src_mask != 0 and "01" not in bin(self.wc.nw_src_mask):
379            wildcards &= ~ofproto_v1_0.OFPFW_NW_SRC_MASK
380            maskbits = (bin(self.wc.nw_src_mask).count("0") - 1)
381            wildcards |= (maskbits << ofproto_v1_0.OFPFW_NW_SRC_SHIFT)
382
383        if self.wc.nw_dst_mask != 0 and "01" not in bin(self.wc.nw_dst_mask):
384            wildcards &= ~ofproto_v1_0.OFPFW_NW_DST_MASK
385            maskbits = (bin(self.wc.nw_dst_mask).count("0") - 1)
386            wildcards |= (maskbits << ofproto_v1_0.OFPFW_NW_DST_SHIFT)
387
388        if self.flow.tp_src != 0:
389            wildcards &= ~ofproto_v1_0.OFPFW_TP_SRC
390
391        if self.flow.tp_dst != 0:
392            wildcards &= ~ofproto_v1_0.OFPFW_TP_DST
393
394        return (wildcards, self.flow.in_port, self.flow.dl_src,
395                self.flow.dl_dst, self.flow.dl_vlan, self.flow.dl_vlan_pcp,
396                self.flow.dl_type, self.flow.nw_tos & IP_DSCP_MASK,
397                self.flow.nw_proto, self.flow.nw_src, self.flow.nw_dst,
398                self.flow.tp_src, self.flow.tp_dst)
399
400
401def _set_nxm_headers(nxm_headers):
402    '''Annotate corresponding NXM header'''
403
404    def _set_nxm_headers_dec(self):
405        self.nxm_headers = nxm_headers
406        return self
407    return _set_nxm_headers_dec
408
409
410def _register_make(cls):
411    '''class decorator to Register mf make'''
412    assert cls.nxm_headers is not None
413    assert cls.nxm_headers is not []
414    for nxm_header in cls.nxm_headers:
415        assert nxm_header not in _MF_FIELDS
416        _MF_FIELDS[nxm_header] = cls.make
417    return cls
418
419
420def mf_from_nxm_header(nxm_header):
421    if nxm_header not in _MF_FIELDS:
422        return None
423    make = _MF_FIELDS.get(nxm_header)
424    assert make is not None
425    return make(nxm_header)
426
427
428class MFField(object):
429    _FIELDS_HEADERS = {}
430
431    @staticmethod
432    def register_field_header(headers):
433        def _register_field_header(cls):
434            for header in headers:
435                MFField._FIELDS_HEADERS[header] = cls
436            return cls
437        return _register_field_header
438
439    def __init__(self, nxm_header, pack_str):
440        self.nxm_header = nxm_header
441        self.pack_str = pack_str
442        self.n_bytes = struct.calcsize(pack_str)
443        self.n_bits = self.n_bytes * 8
444
445    @classmethod
446    def parser(cls, buf, offset):
447        (header,) = struct.unpack_from('!I', buf, offset)
448
449        cls_ = MFField._FIELDS_HEADERS.get(header)
450
451        if cls_:
452            field = cls_.field_parser(header, buf, offset)
453        else:
454            # print 'unknown field type'
455            raise
456        field.length = (header & 0xff) + 4
457
458        return field
459
460    @classmethod
461    def field_parser(cls, header, buf, offset):
462        hasmask = (header >> 8) & 1
463        mask = None
464        if hasmask:
465            pack_str = '!' + cls.pack_str[1:] * 2
466            (value, mask) = struct.unpack_from(pack_str, buf,
467                                               offset + 4)
468        else:
469            (value,) = struct.unpack_from(cls.pack_str, buf,
470                                          offset + 4)
471        return cls(header, value, mask)
472
473    def _put(self, buf, offset, value):
474        msg_pack_into(self.pack_str, buf, offset, value)
475        return self.n_bytes
476
477    def putw(self, buf, offset, value, mask):
478        len_ = self._put(buf, offset, value)
479        return len_ + self._put(buf, offset + len_, mask)
480
481    def _is_all_ones(self, value):
482        return value == (1 << self.n_bits) - 1
483
484    def putm(self, buf, offset, value, mask):
485        if mask == 0:
486            return 0
487        elif self._is_all_ones(mask):
488            return self._put(buf, offset, value)
489        else:
490            return self.putw(buf, offset, value, mask)
491
492    def _putv6(self, buf, offset, value):
493        msg_pack_into(self.pack_str, buf, offset, *value)
494        return self.n_bytes
495
496    def putv6(self, buf, offset, value, mask):
497        len_ = self._putv6(buf, offset, value)
498        if len(mask):
499            return len_ + self._putv6(buf, offset + len_, mask)
500        return len_
501
502
503@_register_make
504@_set_nxm_headers([ofproto_v1_0.NXM_OF_IN_PORT])
505@MFField.register_field_header([ofproto_v1_0.NXM_OF_IN_PORT])
506class MFInPort(MFField):
507    pack_str = MF_PACK_STRING_BE16
508
509    def __init__(self, header, value, mask=None):
510        super(MFInPort, self).__init__(header, MFInPort.pack_str)
511        self.value = value
512
513    @classmethod
514    def make(cls, header):
515        return cls(header, MFInPort.pack_str)
516
517    def put(self, buf, offset, rule):
518        return self._put(buf, offset, rule.flow.in_port)
519
520
521@_register_make
522@_set_nxm_headers([ofproto_v1_0.NXM_OF_ETH_DST, ofproto_v1_0.NXM_OF_ETH_DST_W])
523@MFField.register_field_header([ofproto_v1_0.NXM_OF_ETH_DST,
524                                ofproto_v1_0.NXM_OF_ETH_DST_W])
525class MFEthDst(MFField):
526    pack_str = MF_PACK_STRING_MAC
527
528    def __init__(self, header, value, mask=None):
529        super(MFEthDst, self).__init__(header, MFEthDst.pack_str)
530        self.value = value
531
532    @classmethod
533    def make(cls, header):
534        return cls(header, MFEthDst.pack_str)
535
536    def put(self, buf, offset, rule):
537        if rule.wc.dl_dst_mask:
538            return self.putw(buf, offset, rule.flow.dl_dst,
539                             rule.wc.dl_dst_mask)
540        else:
541            return self._put(buf, offset, rule.flow.dl_dst)
542
543
544@_register_make
545@_set_nxm_headers([ofproto_v1_0.NXM_OF_ETH_SRC, ofproto_v1_0.NXM_OF_ETH_SRC_W])
546@MFField.register_field_header([ofproto_v1_0.NXM_OF_ETH_SRC,
547                                ofproto_v1_0.NXM_OF_ETH_SRC_W])
548class MFEthSrc(MFField):
549    pack_str = MF_PACK_STRING_MAC
550
551    def __init__(self, header, value, mask=None):
552        super(MFEthSrc, self).__init__(header, MFEthSrc.pack_str)
553        self.value = value
554
555    @classmethod
556    def make(cls, header):
557        return cls(header, MFEthSrc.pack_str)
558
559    def put(self, buf, offset, rule):
560        if rule.wc.dl_src_mask:
561            return self.putw(buf, offset, rule.flow.dl_src,
562                             rule.wc.dl_src_mask)
563        else:
564            return self._put(buf, offset, rule.flow.dl_src)
565
566
567@_register_make
568@_set_nxm_headers([ofproto_v1_0.NXM_OF_ETH_TYPE])
569@MFField.register_field_header([ofproto_v1_0.NXM_OF_ETH_TYPE])
570class MFEthType(MFField):
571    pack_str = MF_PACK_STRING_BE16
572
573    def __init__(self, header, value, mask=None):
574        super(MFEthType, self).__init__(header, MFEthType.pack_str)
575        self.value = value
576
577    @classmethod
578    def make(cls, header):
579        return cls(header, MFEthType.pack_str)
580
581    def put(self, buf, offset, rule):
582        return self._put(buf, offset, rule.flow.dl_type)
583
584
585@_register_make
586@_set_nxm_headers([ofproto_v1_0.NXM_OF_VLAN_TCI,
587                   ofproto_v1_0.NXM_OF_VLAN_TCI_W])
588@MFField.register_field_header([ofproto_v1_0.NXM_OF_VLAN_TCI,
589                                ofproto_v1_0.NXM_OF_VLAN_TCI_W])
590class MFVlan(MFField):
591    pack_str = MF_PACK_STRING_BE16
592
593    def __init__(self, header, value, mask=None):
594        super(MFVlan, self).__init__(header, MFVlan.pack_str)
595        self.value = value
596
597    @classmethod
598    def make(cls, header):
599        return cls(header, MFVlan.pack_str)
600
601    def put(self, buf, offset, rule):
602        return self.putm(buf, offset, rule.flow.vlan_tci,
603                         rule.wc.vlan_tci_mask)
604
605
606@_register_make
607@_set_nxm_headers([ofproto_v1_0.NXM_OF_IP_TOS])
608@MFField.register_field_header([ofproto_v1_0.NXM_OF_IP_TOS])
609class MFIPDSCP(MFField):
610    pack_str = MF_PACK_STRING_8
611
612    def __init__(self, header, value, mask=None):
613        super(MFIPDSCP, self).__init__(header, MFIPDSCP.pack_str)
614        self.value = value
615
616    @classmethod
617    def make(cls, header):
618        return cls(header, MFIPDSCP.pack_str)
619
620    def put(self, buf, offset, rule):
621        return self._put(buf, offset,
622                         rule.flow.nw_tos & IP_DSCP_MASK)
623
624
625@_register_make
626@_set_nxm_headers([ofproto_v1_0.NXM_NX_TUN_ID,
627                   ofproto_v1_0.NXM_NX_TUN_ID_W])
628@MFField.register_field_header([ofproto_v1_0.NXM_NX_TUN_ID,
629                                ofproto_v1_0.NXM_NX_TUN_ID_W])
630class MFTunId(MFField):
631    pack_str = MF_PACK_STRING_BE64
632
633    def __init__(self, header, value, mask=None):
634        super(MFTunId, self).__init__(header, MFTunId.pack_str)
635        self.value = value
636
637    @classmethod
638    def make(cls, header):
639        return cls(header, MFTunId.pack_str)
640
641    def put(self, buf, offset, rule):
642        return self.putm(buf, offset, rule.flow.tun_id, rule.wc.tun_id_mask)
643
644
645@_register_make
646@_set_nxm_headers([ofproto_v1_0.NXM_OF_IP_SRC, ofproto_v1_0.NXM_OF_IP_SRC_W])
647@MFField.register_field_header([ofproto_v1_0.NXM_OF_IP_SRC,
648                                ofproto_v1_0.NXM_OF_IP_SRC_W])
649class MFIPSrc(MFField):
650    pack_str = MF_PACK_STRING_BE32
651
652    def __init__(self, header, value, mask=None):
653        super(MFIPSrc, self).__init__(header, MFIPSrc.pack_str)
654        self.value = value
655        self.mask = mask
656
657    @classmethod
658    def make(cls, header):
659        return cls(header, MFIPSrc.pack_str)
660
661    def put(self, buf, offset, rule):
662        return self.putm(buf, offset, rule.flow.nw_src, rule.wc.nw_src_mask)
663
664
665@_register_make
666@_set_nxm_headers([ofproto_v1_0.NXM_OF_IP_DST, ofproto_v1_0.NXM_OF_IP_DST_W])
667@MFField.register_field_header([ofproto_v1_0.NXM_OF_IP_DST,
668                                ofproto_v1_0.NXM_OF_IP_DST_W])
669class MFIPDst(MFField):
670    pack_str = MF_PACK_STRING_BE32
671
672    def __init__(self, header, value, mask=None):
673        super(MFIPDst, self).__init__(header, MFIPDst.pack_str)
674        self.value = value
675        self.mask = mask
676
677    @classmethod
678    def make(cls, header):
679        return cls(header, MFIPDst.pack_str)
680
681    def put(self, buf, offset, rule):
682        return self.putm(buf, offset, rule.flow.nw_dst, rule.wc.nw_dst_mask)
683
684
685@_register_make
686@_set_nxm_headers([ofproto_v1_0.NXM_NX_IP_ECN])
687class MFIPECN(MFField):
688    @classmethod
689    def make(cls, header):
690        return cls(header, MF_PACK_STRING_8)
691
692    def put(self, buf, offset, rule):
693        return self._put(buf, offset,
694                         rule.flow.nw_tos & IP_ECN_MASK)
695
696
697@_register_make
698@_set_nxm_headers([ofproto_v1_0.NXM_NX_IP_TTL])
699class MFIPTTL(MFField):
700    @classmethod
701    def make(cls, header):
702        return cls(header, MF_PACK_STRING_8)
703
704    def put(self, buf, offset, rule):
705        return self._put(buf, offset, rule.flow.nw_ttl)
706
707
708@_register_make
709@_set_nxm_headers([ofproto_v1_0.NXM_OF_IP_PROTO])
710class MFIPProto(MFField):
711    @classmethod
712    def make(cls, header):
713        return cls(header, MF_PACK_STRING_8)
714
715    def put(self, buf, offset, rule):
716        return self._put(buf, offset, rule.flow.nw_proto)
717
718
719@_register_make
720@_set_nxm_headers([ofproto_v1_0.NXM_OF_TCP_SRC, ofproto_v1_0.NXM_OF_TCP_SRC_W,
721                   ofproto_v1_0.NXM_OF_UDP_SRC, ofproto_v1_0.NXM_OF_UDP_SRC_W])
722class MFTPSRC(MFField):
723    @classmethod
724    def make(cls, header):
725        return cls(header, MF_PACK_STRING_BE16)
726
727    def put(self, buf, offset, rule):
728        return self.putm(buf, offset, rule.flow.tp_src, rule.wc.tp_src_mask)
729
730
731@_register_make
732@_set_nxm_headers([ofproto_v1_0.NXM_OF_TCP_DST, ofproto_v1_0.NXM_OF_TCP_DST_W,
733                   ofproto_v1_0.NXM_OF_UDP_DST, ofproto_v1_0.NXM_OF_UDP_DST_W])
734class MFTPDST(MFField):
735    @classmethod
736    def make(cls, header):
737        return cls(header, MF_PACK_STRING_BE16)
738
739    def put(self, buf, offset, rule):
740        return self.putm(buf, offset, rule.flow.tp_dst, rule.wc.tp_dst_mask)
741
742
743@_register_make
744@_set_nxm_headers([ofproto_v1_0.NXM_OF_ARP_SPA, ofproto_v1_0.NXM_OF_ARP_SPA_W])
745class MFArpSpa(MFField):
746    @classmethod
747    def make(cls, header):
748        return cls(header, MF_PACK_STRING_BE32)
749
750    def put(self, buf, offset, rule):
751        return self.putm(buf, offset, rule.flow.arp_spa, rule.wc.arp_spa_mask)
752
753
754@_register_make
755@_set_nxm_headers([ofproto_v1_0.NXM_OF_ARP_TPA, ofproto_v1_0.NXM_OF_ARP_TPA_W])
756class MFArpTpa(MFField):
757    @classmethod
758    def make(cls, header):
759        return cls(header, MF_PACK_STRING_BE32)
760
761    def put(self, buf, offset, rule):
762        return self.putm(buf, offset, rule.flow.arp_tpa, rule.wc.arp_tpa_mask)
763
764
765@_register_make
766@_set_nxm_headers([ofproto_v1_0.NXM_NX_ARP_SHA])
767class MFArpSha(MFField):
768    @classmethod
769    def make(cls, header):
770        return cls(header, MF_PACK_STRING_MAC)
771
772    def put(self, buf, offset, rule):
773        return self._put(buf, offset, rule.flow.arp_sha)
774
775
776class MFIPV6(object):
777    pack_str = MF_PACK_STRING_IPV6
778
779    @classmethod
780    def field_parser(cls, header, buf, offset):
781        hasmask = (header >> 8) & 1
782        if hasmask:
783            pack_string = '!' + cls.pack_str[1:] * 2
784            value = struct.unpack_from(pack_string, buf, offset + 4)
785            return cls(header, list(value[:8]), list(value[8:]))
786        else:
787            value = struct.unpack_from(cls.pack_str, buf, offset + 4)
788            return cls(header, list(value))
789
790
791@_register_make
792@_set_nxm_headers([ofproto_v1_0.NXM_NX_IPV6_SRC,
793                   ofproto_v1_0.NXM_NX_IPV6_SRC_W])
794@MFField.register_field_header([ofproto_v1_0.NXM_NX_IPV6_SRC,
795                                ofproto_v1_0.NXM_NX_IPV6_SRC_W])
796class MFIPV6Src(MFIPV6, MFField):
797    def __init__(self, header, value, mask=None):
798        super(MFIPV6Src, self).__init__(header, MFIPV6Src.pack_str)
799        self.value = value
800        self.mask = mask
801
802    @classmethod
803    def make(cls, header):
804        return cls(header, cls.pack_str)
805
806    def put(self, buf, offset, rule):
807        return self.putv6(buf, offset,
808                          rule.flow.ipv6_src,
809                          rule.wc.ipv6_src_mask)
810
811
812@_register_make
813@_set_nxm_headers([ofproto_v1_0.NXM_NX_IPV6_DST,
814                   ofproto_v1_0.NXM_NX_IPV6_DST_W])
815@MFField.register_field_header([ofproto_v1_0.NXM_NX_IPV6_DST,
816                                ofproto_v1_0.NXM_NX_IPV6_DST_W])
817class MFIPV6Dst(MFIPV6, MFField):
818    def __init__(self, header, value, mask=None):
819        super(MFIPV6Dst, self).__init__(header, MFIPV6Dst.pack_str)
820        self.value = value
821        self.mask = mask
822
823    @classmethod
824    def make(cls, header):
825        return cls(header, cls.pack_str)
826
827    def put(self, buf, offset, rule):
828        return self.putv6(buf, offset,
829                          rule.flow.ipv6_dst,
830                          rule.wc.ipv6_dst_mask)
831
832
833@_register_make
834@_set_nxm_headers([ofproto_v1_0.NXM_NX_ND_TARGET,
835                   ofproto_v1_0.NXM_NX_ND_TARGET_W])
836class MFNdTarget(MFField):
837    @classmethod
838    def make(cls, header):
839        return cls(header, '!4I')
840
841    def put(self, buf, offset, rule):
842        return self.putv6(buf, offset,
843                          rule.flow.nd_target,
844                          rule.wc.nd_target_mask)
845
846
847@_register_make
848@_set_nxm_headers([ofproto_v1_0.NXM_NX_IP_FRAG,
849                   ofproto_v1_0.NXM_NX_IP_FRAG_W])
850class MFIpFrag(MFField):
851    @classmethod
852    def make(cls, header):
853        return cls(header, '!B')
854
855    def put(self, buf, offset, rule):
856        if rule.wc.nw_frag_mask == FLOW_NW_FRAG_MASK:
857            return self._put(buf, offset, rule.flow.nw_frag)
858        else:
859            return self.putw(buf, offset, rule.flow.nw_frag,
860                             rule.wc.nw_frag_mask & FLOW_NW_FRAG_MASK)
861
862
863@_register_make
864@_set_nxm_headers([ofproto_v1_0.NXM_NX_ARP_THA])
865class MFArpTha(MFField):
866    @classmethod
867    def make(cls, header):
868        return cls(header, MF_PACK_STRING_MAC)
869
870    def put(self, buf, offset, rule):
871        return self._put(buf, offset, rule.flow.arp_tha)
872
873
874@_register_make
875@_set_nxm_headers([ofproto_v1_0.NXM_OF_ICMP_TYPE])
876class MFICMPType(MFField):
877    @classmethod
878    def make(cls, header):
879        return cls(header, MF_PACK_STRING_8)
880
881    def put(self, buf, offset, rule):
882        return self._put(buf, offset, rule.flow.tp_src)
883
884
885@_register_make
886@_set_nxm_headers([ofproto_v1_0.NXM_OF_ICMP_CODE])
887class MFICMPCode(MFField):
888    @classmethod
889    def make(cls, header):
890        return cls(header, MF_PACK_STRING_8)
891
892    def put(self, buf, offset, rule):
893        return self._put(buf, offset, rule.flow.tp_dst)
894
895
896@_register_make
897@_set_nxm_headers([ofproto_v1_0.NXM_NX_ICMPV6_TYPE])
898class MFICMPV6Type(MFField):
899    @classmethod
900    def make(cls, header):
901        return cls(header, MF_PACK_STRING_8)
902
903    def put(self, buf, offset, rule):
904        return self._put(buf, offset, rule.flow.tp_src)
905
906
907@_register_make
908@_set_nxm_headers([ofproto_v1_0.NXM_NX_ICMPV6_CODE])
909class MFICMPV6Code(MFField):
910    @classmethod
911    def make(cls, header):
912        return cls(header, MF_PACK_STRING_8)
913
914    def put(self, buf, offset, rule):
915        return self._put(buf, offset, rule.flow.tp_dst)
916
917
918@_register_make
919@_set_nxm_headers([ofproto_v1_0.NXM_NX_IPV6_LABEL])
920class MFICMPV6Label(MFField):
921    @classmethod
922    def make(cls, header):
923        return cls(header, MF_PACK_STRING_BE32)
924
925    def put(self, buf, offset, rule):
926        return self._put(buf, offset, rule.flow.ipv6_label)
927
928
929@_register_make
930@_set_nxm_headers([ofproto_v1_0.nxm_nx_reg(i) for i in range(FLOW_N_REGS)]
931                  + [ofproto_v1_0.nxm_nx_reg_w(i) for i in range(FLOW_N_REGS)])
932class MFRegister(MFField):
933    @classmethod
934    def make(cls, header):
935        return cls(header, MF_PACK_STRING_BE32)
936
937    def put(self, buf, offset, rule):
938        for i in range(FLOW_N_REGS):
939            if (ofproto_v1_0.nxm_nx_reg(i) == self.nxm_header or
940                    ofproto_v1_0.nxm_nx_reg_w(i) == self.nxm_header):
941                if rule.wc.regs_mask[i]:
942                    return self.putm(buf, offset, rule.flow.regs[i],
943                                     rule.wc.regs_mask[i])
944                else:
945                    return self._put(buf, offset, rule.flow.regs[i])
946
947
948@_register_make
949@_set_nxm_headers([ofproto_v1_0.NXM_NX_PKT_MARK,
950                   ofproto_v1_0.NXM_NX_PKT_MARK_W])
951class MFPktMark(MFField):
952    @classmethod
953    def make(cls, header):
954        return cls(header, MF_PACK_STRING_BE32)
955
956    def put(self, buf, offset, rule):
957        return self.putm(buf, offset, rule.flow.pkt_mark,
958                         rule.wc.pkt_mark_mask)
959
960
961@_register_make
962@_set_nxm_headers([ofproto_v1_0.NXM_NX_TCP_FLAGS,
963                   ofproto_v1_0.NXM_NX_TCP_FLAGS_W])
964class MFTcpFlags(MFField):
965    @classmethod
966    def make(cls, header):
967        return cls(header, MF_PACK_STRING_BE16)
968
969    def put(self, buf, offset, rule):
970        return self.putm(buf, offset, rule.flow.tcp_flags,
971                         rule.wc.tcp_flags_mask)
972
973
974def serialize_nxm_match(rule, buf, offset):
975    old_offset = offset
976
977    if not rule.wc.wildcards & FWW_IN_PORT:
978        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_IN_PORT, rule)
979
980    # Ethernet.
981    if rule.flow.dl_dst != mac.DONTCARE:
982        if rule.wc.dl_dst_mask:
983            header = ofproto_v1_0.NXM_OF_ETH_DST_W
984        else:
985            header = ofproto_v1_0.NXM_OF_ETH_DST
986        offset += nxm_put(buf, offset, header, rule)
987
988    if rule.flow.dl_src != mac.DONTCARE:
989        if rule.wc.dl_src_mask:
990            header = ofproto_v1_0.NXM_OF_ETH_SRC_W
991        else:
992            header = ofproto_v1_0.NXM_OF_ETH_SRC
993        offset += nxm_put(buf, offset, header, rule)
994
995    if not rule.wc.wildcards & FWW_DL_TYPE:
996        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_ETH_TYPE, rule)
997
998    # 802.1Q
999    if rule.wc.vlan_tci_mask != 0:
1000        if rule.wc.vlan_tci_mask == UINT16_MAX:
1001            header = ofproto_v1_0.NXM_OF_VLAN_TCI
1002        else:
1003            header = ofproto_v1_0.NXM_OF_VLAN_TCI_W
1004        offset += nxm_put(buf, offset, header, rule)
1005
1006    # L3
1007    if not rule.wc.wildcards & FWW_NW_DSCP:
1008        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_IP_TOS, rule)
1009    if not rule.wc.wildcards & FWW_NW_ECN:
1010        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_IP_ECN, rule)
1011    if not rule.wc.wildcards & FWW_NW_TTL:
1012        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_IP_TTL, rule)
1013    if not rule.wc.wildcards & FWW_NW_PROTO:
1014        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_IP_PROTO, rule)
1015
1016    if not rule.wc.wildcards & FWW_NW_PROTO and (rule.flow.nw_proto
1017                                                 == inet.IPPROTO_ICMP):
1018        if rule.wc.tp_src_mask != 0:
1019            offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_ICMP_TYPE, rule)
1020        if rule.wc.tp_dst_mask != 0:
1021            offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_ICMP_CODE, rule)
1022
1023    if rule.flow.tp_src != 0:
1024        if rule.flow.nw_proto == 6:
1025            if rule.wc.tp_src_mask == UINT16_MAX:
1026                header = ofproto_v1_0.NXM_OF_TCP_SRC
1027            else:
1028                header = ofproto_v1_0.NXM_OF_TCP_SRC_W
1029        elif rule.flow.nw_proto == 17:
1030            if rule.wc.tp_src_mask == UINT16_MAX:
1031                header = ofproto_v1_0.NXM_OF_UDP_SRC
1032            else:
1033                header = ofproto_v1_0.NXM_OF_UDP_SRC_W
1034        else:
1035            header = 0
1036        if header != 0:
1037            offset += nxm_put(buf, offset, header, rule)
1038
1039    if rule.flow.tp_dst != 0:
1040        if rule.flow.nw_proto == 6:
1041            if rule.wc.tp_dst_mask == UINT16_MAX:
1042                header = ofproto_v1_0.NXM_OF_TCP_DST
1043            else:
1044                header = ofproto_v1_0.NXM_OF_TCP_DST_W
1045        elif rule.flow.nw_proto == 17:
1046            if rule.wc.tp_dst_mask == UINT16_MAX:
1047                header = ofproto_v1_0.NXM_OF_UDP_DST
1048            else:
1049                header = ofproto_v1_0.NXM_OF_UDP_DST_W
1050        else:
1051            header = 0
1052        if header != 0:
1053            offset += nxm_put(buf, offset, header, rule)
1054
1055    if rule.flow.tcp_flags != 0:
1056        # TCP Flags can only be used if the ethernet type is IPv4 or IPv6
1057        if rule.flow.dl_type in (ether.ETH_TYPE_IP, ether.ETH_TYPE_IPV6):
1058            # TCP Flags can only be used if the ip protocol is TCP
1059            if rule.flow.nw_proto == inet.IPPROTO_TCP:
1060                if rule.wc.tcp_flags_mask == UINT16_MAX:
1061                    header = ofproto_v1_0.NXM_NX_TCP_FLAGS
1062                else:
1063                    header = ofproto_v1_0.NXM_NX_TCP_FLAGS_W
1064            else:
1065                header = 0
1066        else:
1067            header = 0
1068        if header != 0:
1069            offset += nxm_put(buf, offset, header, rule)
1070
1071    # IP Source and Destination
1072    if rule.flow.nw_src != 0:
1073        if rule.wc.nw_src_mask == UINT32_MAX:
1074            header = ofproto_v1_0.NXM_OF_IP_SRC
1075        else:
1076            header = ofproto_v1_0.NXM_OF_IP_SRC_W
1077        offset += nxm_put(buf, offset, header, rule)
1078
1079    if rule.flow.nw_dst != 0:
1080        if rule.wc.nw_dst_mask == UINT32_MAX:
1081            header = ofproto_v1_0.NXM_OF_IP_DST
1082        else:
1083            header = ofproto_v1_0.NXM_OF_IP_DST_W
1084        offset += nxm_put(buf, offset, header, rule)
1085
1086    # IPv6
1087    if not rule.wc.wildcards & FWW_NW_PROTO and (rule.flow.nw_proto
1088                                                 == inet.IPPROTO_ICMPV6):
1089        if rule.wc.tp_src_mask != 0:
1090            offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_ICMPV6_TYPE,
1091                              rule)
1092        if rule.wc.tp_dst_mask != 0:
1093            offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_ICMPV6_CODE,
1094                              rule)
1095
1096    if not rule.wc.wildcards & FWW_IPV6_LABEL:
1097        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_IPV6_LABEL, rule)
1098
1099    if len(rule.flow.ipv6_src):
1100        if len(rule.wc.ipv6_src_mask):
1101            header = ofproto_v1_0.NXM_NX_IPV6_SRC_W
1102        else:
1103            header = ofproto_v1_0.NXM_NX_IPV6_SRC
1104        offset += nxm_put(buf, offset, header, rule)
1105
1106    if len(rule.flow.ipv6_dst):
1107        if len(rule.wc.ipv6_dst_mask):
1108            header = ofproto_v1_0.NXM_NX_IPV6_DST_W
1109        else:
1110            header = ofproto_v1_0.NXM_NX_IPV6_DST
1111        offset += nxm_put(buf, offset, header, rule)
1112
1113    if len(rule.flow.nd_target):
1114        if len(rule.wc.nd_target_mask):
1115            header = ofproto_v1_0.NXM_NX_ND_TARGET_W
1116        else:
1117            header = ofproto_v1_0.NXM_NX_ND_TARGET
1118        offset += nxm_put(buf, offset, header, rule)
1119
1120    # ARP
1121    if rule.flow.arp_spa != 0:
1122        if rule.wc.arp_spa_mask == UINT32_MAX:
1123            header = ofproto_v1_0.NXM_OF_ARP_SPA
1124        else:
1125            header = ofproto_v1_0.NXM_OF_ARP_SPA_W
1126        offset += nxm_put(buf, offset, header, rule)
1127
1128    if rule.flow.arp_tpa != 0:
1129        if rule.wc.arp_tpa_mask == UINT32_MAX:
1130            header = ofproto_v1_0.NXM_OF_ARP_TPA
1131        else:
1132            header = ofproto_v1_0.NXM_OF_ARP_TPA_W
1133        offset += nxm_put(buf, offset, header, rule)
1134
1135    if not rule.wc.wildcards & FWW_ARP_SHA:
1136        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_ARP_SHA, rule)
1137    if not rule.wc.wildcards & FWW_ARP_THA:
1138        offset += nxm_put(buf, offset, ofproto_v1_0.NXM_NX_ARP_THA, rule)
1139
1140    if rule.flow.nw_frag:
1141        if rule.wc.nw_frag_mask == FLOW_NW_FRAG_MASK:
1142            header = ofproto_v1_0.NXM_NX_IP_FRAG
1143        else:
1144            header = ofproto_v1_0.NXM_NX_IP_FRAG_W
1145        offset += nxm_put(buf, offset, header, rule)
1146
1147    if rule.flow.pkt_mark != 0:
1148        if rule.wc.pkt_mark_mask == UINT32_MAX:
1149            header = ofproto_v1_0.NXM_NX_PKT_MARK
1150        else:
1151            header = ofproto_v1_0.NXM_NX_PKT_MARK_W
1152        offset += nxm_put(buf, offset, header, rule)
1153
1154    # Tunnel Id
1155    if rule.wc.tun_id_mask != 0:
1156        if rule.wc.tun_id_mask == UINT64_MAX:
1157            header = ofproto_v1_0.NXM_NX_TUN_ID
1158        else:
1159            header = ofproto_v1_0.NXM_NX_TUN_ID_W
1160        offset += nxm_put(buf, offset, header, rule)
1161
1162    # XXX: Cookie
1163
1164    for i in range(FLOW_N_REGS):
1165        if rule.wc.regs_bits & (1 << i):
1166            if rule.wc.regs_mask[i]:
1167                header = ofproto_v1_0.nxm_nx_reg_w(i)
1168            else:
1169                header = ofproto_v1_0.nxm_nx_reg(i)
1170            offset += nxm_put(buf, offset, header, rule)
1171
1172    # Pad
1173    pad_len = round_up(offset) - offset
1174    msg_pack_into("%dx" % pad_len, buf, offset)
1175
1176    # The returned length, the match_len, does not include the pad
1177    return offset - old_offset
1178
1179
1180def nxm_put(buf, offset, header, rule):
1181    nxm = NXMatch(header)
1182    len_ = nxm.put_header(buf, offset)
1183    mf = mf_from_nxm_header(nxm.header)
1184    return len_ + mf.put(buf, offset + len_, rule)
1185
1186
1187def round_up(length):
1188    return (length + 7) // 8 * 8  # Round up to a multiple of 8
1189
1190
1191class NXMatch(object):
1192    def __init__(self, header):
1193        self.header = header
1194
1195    @classmethod
1196    def parser(cls, buf, offset, match_len):
1197        if match_len < 4:
1198            raise exception.OFPMalformedMessage
1199        (header,) = struct.unpack_from(ofproto_v1_0.NXM_HEADER_PACK_STRING,
1200                                       buf, offset)
1201        instance = cls(header)
1202        payload_len = instance.length()
1203        if payload_len == 0 or match_len < payload_len + 4:
1204            raise exception.OFPMalformedMessage
1205        return instance
1206
1207    def vendor(self):
1208        return self.header >> 16
1209
1210    def field(self):
1211        return (self.header >> 9) % 0x7f
1212
1213    def type(self):
1214        return (self.header >> 9) % 0x7fffff
1215
1216    def hasmask(self):
1217        return (self.header >> 8) & 1
1218
1219    def length(self):
1220        return self.header & 0xff
1221
1222    def show(self):
1223        return ('%08x (vendor=%x, field=%x, hasmask=%x len=%x)' %
1224                (self.header, self.vendor(), self.field(),
1225                 self.hasmask(), self.length()))
1226
1227    def put_header(self, buf, offset):
1228        msg_pack_into(ofproto_v1_0.NXM_HEADER_PACK_STRING,
1229                      buf, offset, self.header)
1230        return struct.calcsize(ofproto_v1_0.NXM_HEADER_PACK_STRING)
1231