Ejemplo n.º 1
0
 def natv6_flows(self, nfvip):
     nat_base = nfvip.network.network_address
     assert nfvip.network.prefixlen == 64, 'NFVIPS IPv4 all must be /64'
     # pylint: disable=no-member
     return self.apply_actions([
         # ipv6_src fc01::5 -> fc04::5:0:1, ipv6_dst fc01::1 -> fc04::1
         parser.NXActionRegLoad(value=(int(nat_base) & ((2**64) - 1)),
                                dst=self.AREG,
                                ofs_nbits=nicira_ext.ofs_nbits(0, 63)),
         parser.NXActionRegLoad(value=(int(nat_base) >> 64),
                                dst=self.AREG,
                                ofs_nbits=nicira_ext.ofs_nbits(64, 127)),
     ] + self.nat_actions(ether.ETH_TYPE_IPV6, nfvip, 32))
Ejemplo n.º 2
0
 def arp_reply_actions(self):
     # pylint: disable=no-member
     common_reply = self.common_reply_actions()
     return self.apply_actions([
         parser.NXActionRegLoad(value=arp.ARP_REPLY,
                                dst='arp_op',
                                ofs_nbits=nicira_ext.ofs_nbits(0, 2)),
         parser.NXActionRegMove(src_field='arp_sha',
                                dst_field='arp_tha',
                                n_bits=48,
                                src_ofs=0,
                                dst_ofs=0),
         parser.NXActionRegMove(src_field='arp_tpa',
                                dst_field=self.AREG,
                                n_bits=32,
                                src_ofs=0,
                                dst_ofs=0),
         parser.NXActionRegMove(src_field='arp_spa',
                                dst_field='arp_tpa',
                                n_bits=32,
                                src_ofs=0,
                                dst_ofs=0),
         parser.NXActionRegMove(src_field=self.AREG,
                                dst_field='arp_spa',
                                n_bits=32,
                                src_ofs=0,
                                dst_ofs=0),
         parser.OFPActionSetField(arp_sha=FAKECLIENTMAC),
     ] + common_reply)
Ejemplo n.º 3
0
 def _make_ingress_classification_flow(self, lport, port_num):
     match = self.parser.OFPMatch(in_port=port_num)
     network_id = lport.lswitch.unique_key
     LOG.debug(
         "match in_port=%(in_port)s for ingress classification "
         "of %(lport)s in network %(network)s", {
             'in_port': port_num,
             'lport': lport,
             'network': network_id
         })
     # Reset in_port to 0 to avoid drop by output command.
     actions = [
         self.parser.OFPActionSetField(reg6=lport.unique_key),
         self.parser.OFPActionSetField(metadata=network_id),
         self.parser.NXActionRegLoad(
             dst='in_port',
             value=0,
             ofs_nbits=nicira_ext.ofs_nbits(0, 31),
         ),
         self.parser.NXActionResubmit(),
     ]
     self.mod_flow(
         table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE,
         priority=const.PRIORITY_MEDIUM,
         match=match,
         actions=actions,
     )
Ejemplo n.º 4
0
 def _get_rewrite_ip_and_output_actions(self, ofproto, parser):
     """
     Retrieve the actions that rewrite the dst IP field with the reg6
     (the tunnel key), set the first bit of that field, and output to the
     metadata service OVS port.
     The IP is set to <reg6> | 0x8000000, so that the transparent proxy
     can extract the <reg6> from the source IP address, and be able to
     identify the source VM. reg6 holds the local DF id identifying the VM.
     """
     return [
         parser.NXActionRegMove(
             src_field='reg6',
             dst_field='ipv4_src',
             n_bits=32,
         ),
         parser.NXActionRegLoad(
             ofs_nbits=nicira_ext.ofs_nbits(31, 31),
             dst="ipv4_src",
             value=1,
         ),
         parser.OFPActionOutput(
             self._port_num,
             ofproto.OFPCML_NO_BUFFER,
         )
     ]
Ejemplo n.º 5
0
    def _install_snat_egress_conntrack(self, match, ext_host_ip):
        """implements single sNAT pass for multiple tenant deployment

        :param match: - OVS match expression passed as a parameter
        :param ext_host_ip: - unique ip to translate tenant IPs to it
        :returns: None
        ----Translation logic follows next rules:----

        ipv4_src -> reg5  (temporary save internal tenant local IP)
        reg6 -> ipv4_src  (replace content of ipv4_src with host unique value)
        last_bit(1) -> ipv4_src  (turn unique value into legal IP address)
        reg6-> ct_mark (save unique value associated with port into
                                    OS  conn. track table)
        reg5 -> ct_label (save original tenant local IP for return flow)
        """
        parser = self.parser
        ofproto = self.ofproto

        actions = [
            parser.NXActionRegMove(src_field='ipv4_src',
                                   dst_field='reg5',
                                   n_bits=32),
            parser.NXActionRegMove(src_field='reg6',
                                   dst_field='ipv4_src',
                                   n_bits=32),
            parser.NXActionRegLoad(
                ofs_nbits=nicira_ext.ofs_nbits(31, 31),
                dst="ipv4_src",
                value=1,
            ),
            parser.NXActionCT(alg=0,
                              flags=const.CT_FLAG_COMMIT,
                              recirc_table=const.EGRESS_SNAT_TABLE,
                              zone_ofs_nbits=const.NAT_TRACKING_ZONE,
                              zone_src='',
                              actions=[
                                  parser.NXActionNAT(
                                      flags=const.CT_FLAG_COMMIT,
                                      range_ipv4_min=ext_host_ip,
                                      range_ipv4_max=ext_host_ip,
                                  ),
                                  parser.NXActionRegMove(dst_field='ct_mark',
                                                         src_field='reg6',
                                                         n_bits=32),
                                  parser.NXActionRegMove(dst_field='ct_label',
                                                         src_field='reg5',
                                                         n_bits=32),
                              ])
        ]

        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)

        inst = [action_inst]

        self.mod_flow(inst=inst,
                      table_id=const.EGRESS_NAT_TABLE,
                      priority=const.PRIORITY_LOW,
                      match=match)
Ejemplo n.º 6
0
 def natv4_flows(self, nfvip):
     nat_base = nfvip.network.network_address
     assert nfvip.network.prefixlen == 16, 'NFVIPS IPv4 all must be /16'
     # pylint: disable=no-member
     return self.apply_actions([
         # ipv4_src 192.168.2.5->10.10.5.1, ipv4_dst 192.168.2.1->10.10.0.1
         parser.NXActionRegLoad(value=int(nat_base),
                                dst=self.AREG,
                                ofs_nbits=nicira_ext.ofs_nbits(0, 31)),
     ] + self.nat_actions(ether.ETH_TYPE_IP, nfvip, 8))
Ejemplo n.º 7
0
    def ct(cls, ofproto, action_str):
        str_to_port = {'ftp': 21, 'tftp': 69}
        flags = 0
        zone_src = ""
        zone_ofs_nbits = 0
        recirc_table = nicira_ext.NX_CT_RECIRC_NONE
        alg = 0
        ct_actions = []

        if len(action_str) > 2:
            if (not action_str.startswith('ct(') or action_str[-1] != ')'):
                raise os_ken.exception.OFPInvalidActionString(
                    action_str=action_str)
            rest = tokenize_ofp_instruction_arg(action_str[len('ct('):-1])
        else:
            rest = []
        for arg in rest:
            if arg == 'commit':
                flags |= nicira_ext.NX_CT_F_COMMIT
                rest = rest[len('commit'):]
            elif arg == 'force':
                flags |= nicira_ext.NX_CT_F_FORCE
            elif arg.startswith('exec('):
                ct_actions = ofp_instruction_from_str(ofproto,
                                                      arg[len('exec('):-1])
            else:
                try:
                    k, v = arg.split('=', 1)
                    if k == 'table':
                        recirc_table = str_to_int(v)
                    elif k == 'zone':
                        m = re.search(r'\[(\d*)\.\.(\d*)\]', v)
                        if m:
                            zone_ofs_nbits = nicira_ext.ofs_nbits(
                                int(m.group(1)), int(m.group(2)))
                            zone_src = nxm_field_name_to_os_ken(v[:m.start(0)])
                        else:
                            zone_ofs_nbits = str_to_int(v)
                    elif k == 'alg':
                        alg = str_to_port[arg[len('alg='):]]
                except Exception:
                    raise os_ken.exception.OFPInvalidActionString(
                        action_str=action_str)
        return dict(
            NXActionCT={
                'flags': flags,
                'zone_src': zone_src,
                'zone_ofs_nbits': zone_ofs_nbits,
                'recirc_table': recirc_table,
                'alg': alg,
                'actions': ct_actions
            })
Ejemplo n.º 8
0
    def _install_snat_ingress_after_conntrack(self, unique_key, vm_mac,
                                              network_id, external_host_mac):
        """complements reverse sNAT translation from unique IP to tenant IP

        :param unique_key: - key to match with
        :param vm_mac: - original VM mac address to restore
        :returns: None

        ---Translation complement follows next rules:---
        unique_key -> reg7 ( load unique port key into dedicated register)
        ct_label -> ipv4_src (restore original local tenant IP)
        change src/dst mac addresses to push packet further to destination
        """
        parser = self.parser
        ofproto = self.ofproto
        match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                ct_mark=int(unique_key))

        actions = [
            parser.OFPActionSetField(eth_src=external_host_mac),
            parser.OFPActionSetField(eth_dst=vm_mac),
            parser.NXActionRegLoad(ofs_nbits=nicira_ext.ofs_nbits(0, 31),
                                   dst='reg7',
                                   value=unique_key),
            parser.NXActionRegMove(src_field='ct_label',
                                   dst_field='ipv4_dst',
                                   n_bits=32),
            parser.OFPActionSetField(metadata=network_id),
        ]
        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)
        goto_inst = parser.OFPInstructionGotoTable(
            const.INGRESS_DESTINATION_PORT_LOOKUP_TABLE)
        inst = [action_inst, goto_inst]

        self.mod_flow(inst=inst,
                      table_id=const.INGRESS_SNAT_TABLE,
                      priority=const.PRIORITY_LOW,
                      match=match)

        actions = [
            self.parser.OFPActionOutput(self.external_ofport,
                                        self.ofproto.OFPCML_NO_BUFFER)
        ]
        self.mod_flow(actions=actions,
                      table_id=const.INGRESS_DISPATCH_TABLE,
                      priority=const.PRIORITY_DEFAULT)
Ejemplo n.º 9
0
    def _install_ingress_goto_rules(self):
        parser = self.parser

        #匹配external_ofport (br-int桥上连接br-ex的port)
        match = parser.OFPMatch(in_port=self.external_ofport)
        actions = [
            parser.NXActionRegLoad(dst='in_port',
                                   value=0,
                                   ofs_nbits=nicira_ext.ofs_nbits(0, 31))
        ]

        inst = [
            parser.OFPInstructionActions(
                self.datapath.ofproto.OFPIT_APPLY_ACTIONS, actions),
            parser.OFPInstructionGotoTable(const.INGRESS_NAT_TABLE)
        ]
        self.mod_flow(inst=inst,
                      table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE,
                      priority=const.PRIORITY_DEFAULT,
                      match=match)
Ejemplo n.º 10
0
    def _install_dispatch_flows(self, flow_classifier):
        lport = self._get_flow_classifier_lport(flow_classifier)
        # End-of-chain
        # 1) Restore network ID in metadata and zero reg6 + reg2
        # 2) Restore port ID in reg7 in dest port
        # 3) Resubmit to the next table
        lswitch = lport.lswitch

        actions = [
            self.parser.OFPActionSetField(metadata=lswitch.unique_key),
            self.parser.OFPActionSetField(reg6=0),
            self.parser.OFPActionSetField(reg2=0),
        ]

        if flow_classifier.source_port == lport:
            done_bit = _SRC_BIT
        elif flow_classifier.dest_port == lport:
            done_bit = _DST_BIT

            # FIXME (dimak) maybe get it from L2 table
            actions.append(
                self.parser.OFPActionSetField(reg7=lport.unique_key))

        actions += [
            self.parser.NXActionRegLoad(
                dst='reg3',
                value=1,
                ofs_nbits=nicira_ext.ofs_nbits(done_bit, done_bit),
            ),
            self.parser.NXActionResubmitTable(
                table_id=self._get_flow_classifier_table(flow_classifier))
        ]

        self.mod_flow(
            table_id=constants.SFC_END_OF_CHAIN_TABLE,
            priority=constants.PRIORITY_MEDIUM,
            match=self.parser.OFPMatch(reg2=flow_classifier.unique_key),
            actions=actions,
        )
Ejemplo n.º 11
0
    def _match_actions_by_network_type(self, lport, network_id, network_type):
        actions = [
            self.parser.NXActionRegLoad(
                dst='in_port',
                value=0,
                ofs_nbits=nicira_ext.ofs_nbits(0, 31),
            ),
            self.parser.OFPActionSetField(metadata=network_id),
        ]

        if network_type == NET_VLAN:
            vlan_vid = self.ofproto.OFPVID_PRESENT
            vlan_vid |= lport.lswitch.segmentation_id
            actions.append(self.parser.OFPActionPopVlan())
        elif network_type == NET_FLAT:
            vlan_vid = 0

        match = self.parser.OFPMatch(
            in_port=self.int_ofports[lport.lswitch.physical_network],
            vlan_vid=vlan_vid,
        )

        return match, actions
Ejemplo n.º 12
0
 def nat_actions(self, eth_type, nfvip, nat_offset):
     ip_ver = nfvip.ip.version
     ip_src_nxm = 'ipv%u_src_nxm' % ip_ver
     ip_dst_nxm = 'ipv%u_dst_nxm' % ip_ver
     ipbits = nfvip.ip.max_prefixlen
     # pylint: disable=no-member
     return [
         parser.NXActionRegMove(src_field='ipv%u_src' % ip_ver,
                                dst_field=self.AREG,
                                n_bits=nat_offset,
                                src_ofs=0,
                                dst_ofs=nat_offset),
         parser.NXActionRegMove(src_field='ipv%u_dst' % ip_ver,
                                dst_field=self.AREG,
                                n_bits=nat_offset,
                                src_ofs=0,
                                dst_ofs=0),
         # we have to load output port numbers into reg1 and reg2 because NXFlowSpecOutput() won't take a literal.
         parser.NXActionRegLoad(value=FAKEPORT,
                                dst=self.FAKEPORTREG,
                                ofs_nbits=nicira_ext.ofs_nbits(0, 15)),
         parser.NXActionRegLoad(value=COPROPORT,
                                dst=self.COPROPORTREG,
                                ofs_nbits=nicira_ext.ofs_nbits(0, 15)),
         # now program an inbound flow to perform NAT.
         parser.NXActionLearn(
             table_id=self.FROM_COPRO_TABLE,
             priority=2,
             hard_timeout=self.IDLE,
             specs=[
                 parser.NXFlowSpecMatch(
                     src=eth_type, dst=('eth_type_nxm', 0), n_bits=16),
                 parser.NXFlowSpecMatch(src=(ip_src_nxm, 0),
                                        dst=(ip_src_nxm, 0),
                                        n_bits=ipbits),
                 parser.NXFlowSpecMatch(src=(ip_dst_nxm, 0),
                                        dst=(ip_dst_nxm, 0),
                                        n_bits=ipbits),
                 parser.NXFlowSpecLoad(src=int(FAKECLIENTMAC),
                                       dst=('eth_src_nxm', 0),
                                       n_bits=48),
                 parser.NXFlowSpecLoad(src=int(FAKESERVERMAC),
                                       dst=('eth_dst_nxm', 0),
                                       n_bits=48),
             ] + self.reg_copy(self.AREG, ip_src_nxm, ipbits) + [
                 parser.NXFlowSpecLoad(
                     src=int(nfvip.ip), dst=(ip_dst_nxm, 0), n_bits=ipbits),
                 parser.NXFlowSpecOutput(
                     src=(self.FAKEPORTREG, 0), dst='', n_bits=16),
             ]),
         # now program outbound an outbound flow.
         parser.NXActionLearn(
             table_id=self.TO_COPRO_TABLE,
             priority=2,
             idle_timeout=self.IDLE,
             specs=[
                 parser.NXFlowSpecMatch(
                     src=eth_type, dst=('eth_type_nxm', 0), n_bits=16),
                 parser.NXFlowSpecMatch(src=int(nfvip.ip),
                                        dst=(ip_src_nxm, 0),
                                        n_bits=ipbits),
             ] + self.reg_copy(self.AREG, ip_dst_nxm, ipbits) + [
                 parser.NXFlowSpecLoad(src=('eth_dst_nxm', 0),
                                       dst=('eth_src_nxm', 0),
                                       n_bits=48),
                 parser.NXFlowSpecLoad(src=('eth_src_nxm', 0),
                                       dst=('eth_dst_nxm', 0),
                                       n_bits=48),
                 parser.NXFlowSpecLoad(src=(ip_dst_nxm, 0),
                                       dst=(ip_src_nxm, 0),
                                       n_bits=ipbits),
                 parser.NXFlowSpecLoad(src=(ip_src_nxm, 0),
                                       dst=(ip_dst_nxm, 0),
                                       n_bits=ipbits),
                 parser.NXFlowSpecOutput(
                     src=(self.COPROPORTREG, 0), dst='', n_bits=16),
             ]),
         # now that future flows are programmed, handle the packet we have.
         parser.OFPActionSetField(eth_src=FAKECLIENTMAC),
         parser.OFPActionSetField(eth_dst=FAKESERVERMAC),
         parser.NXActionRegMove(src_field=self.AREG,
                                dst_field=('ipv%u_src' % ip_ver),
                                n_bits=ipbits,
                                src_ofs=0,
                                dst_ofs=0),
         parser.OFPActionSetField(**{'ipv%u_dst' % ip_ver: str(nfvip.ip)}),
         parser.OFPActionOutput(FAKEPORT)
     ]