Example #1
0
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        match = parser.OFPMatch()
        actions = [
            parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                   ofproto.OFPCML_NO_BUFFER)
        ]
        ofp_helper.add_flow(datapath, 0, match, actions)

        # install DHCP request packets flow entry
        match_dhcp_request = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                             ip_proto=inet.IPPROTO_UDP,
                                             udp_src=68,
                                             udp_dst=67)
        ofp_helper.add_flow(datapath, 100, match_dhcp_request, actions)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        # self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        if in_port == monitor_port:
            # don't mirror snort traffic
            actions = [parser.OFPActionOutput(out_port)]
        else:
            # add mirror port
            actions = [parser.OFPActionOutput(out_port),
                       parser.OFPActionOutput(monitor_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                ofp_helper.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                ofp_helper.add_flow(datapath, 1, match, actions)

        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                  in_port=in_port, actions=actions, data=data)
        datapath.send_msg(out)
Example #3
0
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # ofproto.OFPCML_NO_BUFFER == 65535 (0xFFFF)

        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        match = parser.OFPMatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER)]

        # set miss_send_length to 1518
        self.send_set_config(datapath)

        # get switch config message
        self.send_get_config_request(datapath)

        # install table-miss flow entry
        ofp_helper.add_flow(datapath, 0, match, actions)

        # install DHCP request packets flow entry
        match_dhcp_request = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                             ip_proto=inet.IPPROTO_UDP,
                                             udp_src=68, udp_dst=67)
        ofp_helper.add_flow(datapath, 100, match_dhcp_request, actions)
Example #4
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        nat_settings = settings.load()
        wan_port = nat_settings['wan_port']

        if in_port == wan_port:
            # self.logger.info("ignore packet coming from WAN port 3")
            # ignore packet coming from WAN port
            return
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        # self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        actions = [parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                ofp_helper.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                ofp_helper.add_flow(datapath, 1, match, actions)
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath,
                                  buffer_id=msg.buffer_id,
                                  in_port=in_port,
                                  actions=actions,
                                  data=data)
        datapath.send_msg(out)
Example #5
0
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        match = parser.OFPMatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER)]
        ofp_helper.add_flow(datapath, match=match, actions=actions,
                            idle_timeout=0, priority=0)
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # install table-miss flow entry
        match = parser.OFPMatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER)]
        ofp_helper.add_flow(datapath, 0, match, actions)
Example #7
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        nat_settings = settings.load()
        wan_port = nat_settings['wan_port']

        if in_port == wan_port:
            # self.logger.info("ignore packet coming from WAN port 3")
            # ignore packet coming from WAN port
            return
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        # self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        actions = [parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                ofp_helper.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                ofp_helper.add_flow(datapath, 1, match, actions)
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                  in_port=in_port, actions=actions, data=data)
        datapath.send_msg(out)
Example #8
0
    def _reset_flow(self, datapath):
        parser = datapath.ofproto_parser
        syn_ack_match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                        ip_proto=inet.IPPROTO_TCP,
                                        ipv4_src=syn_flow.get('ip_dst'),
                                        tcp_src=syn_flow.get('port_dst'))

        actions = [parser.OFPActionOutput(13)]

        # to reset counter, delete flow first
        ofp_helper.del_flow(datapath, syn_ack_match, 100)
        ofp_helper.add_flow(datapath, 100, syn_ack_match, actions)
    def _reset_flow(self, datapath):
        parser = datapath.ofproto_parser
        syn_ack_match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                        ip_proto=inet.IPPROTO_TCP,
                                        ipv4_src=syn_flow.get('ip_dst'),
                                        tcp_src=syn_flow.get('port_dst'))

        actions = [parser.OFPActionOutput(13)]

        # to reset counter, delete flow first
        ofp_helper.del_flow(datapath, syn_ack_match, 100)
        ofp_helper.add_flow(datapath, 100, syn_ack_match, actions)
Example #10
0
 def init_packet_in_table(self, datapath):
     parser = datapath.ofproto_parser
     ofproto = datapath.ofproto
     match = parser.OFPMatch()
     actions = [
         parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                ofproto.OFPCML_NO_BUFFER)
     ]
     ofp_helper.add_flow(datapath,
                         table_id=self.count - 1,
                         priority=self.packet_in_priority,
                         match=match,
                         actions=actions,
                         idle_timeout=0)
    def add_block_rule(self, src_ip, dst_ip, protocol, dst_port, src_port):
        switch_list = get_switch(self.topology_api_app, None)
        for switch in switch_list:
            datapath = switch.dp
            parser = datapath.ofproto_parser

            actions = []  # drop

            # initial match field(IP layer)
            match_dict = self.handle_match(src_ip, dst_ip, protocol,
                                           dst_port, src_port)

            match = parser.OFPMatch(**match_dict)
            ofp_helper.add_flow(datapath, fw_priority, match, actions, 30)
Example #12
0
    def add_firewall_rule(self, src_ip, dst_ip, ip_proto, port):
        switch_list = get_switch(self.topology_api_app, None)
        for switch in switch_list:
            datapath = switch.dp
            parser = datapath.ofproto_parser
            ofproto = datapath.ofproto
            match_mapping = self.match_mapping(src_ip, dst_ip, ip_proto, port)
            match = parser.OFPMatch(**match_mapping)

            actions = []  # drop
            ofp_helper.add_flow(datapath,
                                table_id=self.table_id,
                                priority=self.service_priority,
                                match=match,
                                actions=actions)
            self._request_flow_stats(datapath)  # update flow list
Example #13
0
    def _reset_flow(self, datapath):
        parser = datapath.ofproto_parser

        # inport -> outport
        # inport -> mirror port
        in_match = parser.OFPMatch(in_port=port_a)
        in_actions = [parser.OFPActionOutput(port_b),
                      parser.OFPActionOutput(port_ab)]
        ofp_helper.add_flow(datapath, tap_priority, in_match, in_actions)

        # outport -> mirror port
        # outport -> inport
        out_match = parser.OFPMatch(in_port=port_b)
        out_actions = [parser.OFPActionOutput(port_a),
                       parser.OFPActionOutput(port_ab)]
        ofp_helper.add_flow(datapath, tap_priority, out_match, out_actions)
Example #14
0
 def add_packet_in_flow(self, apply_table_id):
     switch_list = get_switch(self.topology_api_app, None)
     for switch in switch_list:
         datapath = switch.dp
         parser = datapath.ofproto_parser
         ofproto = datapath.ofproto
         match = parser.OFPMatch()
         actions = [
             parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                    ofproto.OFPCML_NO_BUFFER)
         ]
         ofp_helper.add_flow(datapath,
                             table_id=apply_table_id,
                             priority=self.packet_in_priority,
                             match=match,
                             actions=actions,
                             idle_timeout=0)
Example #15
0
 def add_dhcp_flow(self):
     switch_list = get_switch(self.topology_api_app, None)
     for switch in switch_list:
         datapath = switch.dp
         parser = datapath.ofproto_parser
         ofproto = datapath.ofproto
         match_dhcp_request = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                              ip_proto=inet.IPPROTO_UDP,
                                              udp_src=68,
                                              udp_dst=67)
         actions = [
             parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                    ofproto.OFPCML_NO_BUFFER)
         ]
         ofp_helper.add_flow(
             datapath,
             table_id=service_config.service_sequence['nat_egress'],
             priority=service_config.service_priority['dhcp'],
             match=match_dhcp_request,
             actions=actions,
             idle_timeout=0)
Example #16
0
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # install DHCP request packets flow entry
        # and dhcp dont need to go to next table
        match_dhcp_request = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                             ip_proto=inet.IPPROTO_UDP,
                                             udp_src=68,
                                             udp_dst=67)
        actions = [
            parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                   ofproto.OFPCML_NO_BUFFER)
        ]
        ofp_helper.add_flow(datapath,
                            table_id=self.table_id,
                            priority=self.service_priority,
                            match=match_dhcp_request,
                            actions=actions,
                            idle_timeout=0)
Example #17
0
    def add_block_rule(self, rule_action, src_ip, dst_ip, trans_proto, port):
        switch_list = get_switch(self.topology_api_app, None)
        for switch in switch_list:
            datapath = switch.dp
            parser = datapath.ofproto_parser
            actions = []  # drop

            # initial match field
            match_dict = {'eth_type': ether.ETH_TYPE_IP}

            # fill into the layer3 and layer 4 protocol
            # if port == 0, means block all protocol
            if port >= 0:
                if trans_proto == inet.IPPROTO_TCP:
                    match_dict.update({
                        'ip_proto': trans_proto,
                        'tcp_dst': port
                    })
                else:  # udp
                    match_dict.update({
                        'ip_proto': trans_proto,
                        'udp_dst': port
                    })

            if len(src_ip) > 0:  # not ''
                match_dict.update({'ipv4_src': src_ip})

            if len(dst_ip) > 0:  # not ''
                match_dict.update({'ipv4_dst': dst_ip})

            match = parser.OFPMatch(**match_dict)

            settings = firewall_settings.load()
            fw_priority = settings['priority']
            if rule_action == 'add':
                ofp_helper.add_flow(datapath, fw_priority, match, actions)
            elif rule_action == 'delete':  # 'off'
                ofp_helper.del_flow(datapath, match, fw_priority)

            self._request_stats(datapath)  # update flow list
Example #18
0
    def add_block_rule(self, rule_action, src_ip, dst_ip, trans_proto, port):
        switch_list = get_switch(self.topology_api_app, None)
        for switch in switch_list:
            datapath = switch.dp
            parser = datapath.ofproto_parser
            actions = []  # drop

            # initial match field
            match_dict = {'eth_type': ether.ETH_TYPE_IP}

            # fill into the layer3 and layer 4 protocol
            # if port == 0, means block all protocol
            if port >= 0:
                if trans_proto == inet.IPPROTO_TCP:
                    match_dict.update({'ip_proto': trans_proto,
                                       'tcp_dst': port})
                else:  # udp
                    match_dict.update({'ip_proto': trans_proto,
                                       'udp_dst': port})

            if len(src_ip) > 0:  # not ''
                match_dict.update({'ipv4_src': src_ip})

            if len(dst_ip) > 0:  # not ''
                match_dict.update({'ipv4_dst': dst_ip})

            match = parser.OFPMatch(**match_dict)

            settings = firewall_settings.load()
            fw_priority = settings['priority']
            if rule_action == 'add':
                ofp_helper.add_flow(datapath, fw_priority, match, actions)
            elif rule_action == 'delete':  # 'off'
                ofp_helper.del_flow(datapath, match, fw_priority)

            self._request_stats(datapath)  # update flow list
Example #19
0
    def _private_to_public(self, datapath, buffer_id, data, in_port, out_port,
                           pkt_ip, pkt_ethernet, pkt_tcp=None, pkt_udp=None,
                           pkt_icmp=None):
        if pkt_ip is None:
            return

        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto

        eth_dst = pkt_ethernet.dst
        eth_src = pkt_ethernet.src
        ipv4_src = pkt_ip.src
        ipv4_dst = pkt_ip.dst

        nat_port = self._get_available_port()

        if (self._is_public(ipv4_dst) and not self._in_nat_public_ip_subnetwork(ipv4_dst)):
            target_ip = self.gateway
        elif self._in_nat_public_ip_subnetwork(ipv4_dst):
            target_ip = ipv4_dst
        elif self._in_private_subnetwork(ipv4_dst):
            return

        if pkt_tcp:
            # print "@@@ Install TCP Flow Entry @@@"
            tcp_src = pkt_tcp.src_port
            tcp_dst = pkt_tcp.dst_port

            match = parser.OFPMatch(in_port=in_port,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ip_proto=inet.IPPROTO_TCP,
                                    ipv4_src=ipv4_src,
                                    ipv4_dst=ipv4_dst,
                                    tcp_src=tcp_src,
                                    tcp_dst=tcp_dst)

            actions = [parser.OFPActionSetField(eth_dst=IP_TO_MAC_TABLE[target_ip]),
                       parser.OFPActionSetField(ipv4_src=self.nat_public_ip),
                       parser.OFPActionSetField(tcp_src=nat_port),
                       parser.OFPActionOutput(out_port)]

            match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                         ip_proto=inet.IPPROTO_TCP,
                                         ipv4_src=ipv4_dst,
                                         ipv4_dst=self.nat_public_ip,
                                         tcp_src=tcp_dst,
                                         tcp_dst=nat_port)

            actions_back = [parser.OFPActionSetField(eth_dst=eth_src),
                            parser.OFPActionSetField(ipv4_dst=ipv4_src),
                            parser.OFPActionSetField(tcp_dst=tcp_src),
                            parser.OFPActionOutput(in_port)]
        elif pkt_udp:
            # print "@@@ Install UDP Flow Entry @@@"
            udp_src = pkt_udp.src_port
            udp_dst = pkt_udp.dst_port

            match = parser.OFPMatch(in_port=in_port,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ip_proto=inet.IPPROTO_UDP,
                                    ipv4_src=ipv4_src,
                                    ipv4_dst=ipv4_dst,
                                    udp_src=udp_src,
                                    udp_dst=udp_dst)

            actions = [parser.OFPActionSetField(eth_dst=IP_TO_MAC_TABLE[target_ip]),
                       parser.OFPActionSetField(ipv4_src=self.nat_public_ip),
                       parser.OFPActionSetField(udp_src=nat_port),
                       parser.OFPActionOutput(out_port)]

            match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                         ip_proto=inet.IPPROTO_UDP,
                                         ipv4_src=ipv4_dst,
                                         ipv4_dst=self.nat_public_ip,
                                         udp_src=udp_dst,
                                         udp_dst=nat_port)

            actions_back = [parser.OFPActionSetField(eth_dst=eth_src),
                            parser.OFPActionSetField(ipv4_dst=ipv4_src),
                            parser.OFPActionSetField(udp_dst=udp_src),
                            parser.OFPActionOutput(in_port)]
        else:
            pass

        ofp_helper.add_flow(datapath, match=match, actions=actions,
                            idle_timeout=self.IDLE_TIME, priority=10)
        ofp_helper.add_flow(datapath, match=match_back, actions=actions_back,
                            idle_timeout=self.IDLE_TIME, priority=10)

        d = None
        if buffer_id == ofproto.OFP_NO_BUFFER:
            d = data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id,
                                  in_port=in_port, actions=actions, data=d)
        datapath.send_msg(out)
Example #20
0
    def _handle_ipv4(self, msg, in_port, pkt, pkt_ethernet, pkt_ipv4):
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id

        eth_dst = pkt_ethernet.dst
        eth_src = pkt_ethernet.src

        # update ip info for members in member_list
        member_list = forwarding_config.member_list
        dst_member = member_list[eth_dst]
        dst_member.ip = pkt_ipv4.dst
        if member_list.get(eth_src) is not None:
            src_member = member_list[eth_src]
            src_member.ip = pkt_ipv4.src
        out_port = dst_member.port

        # install layer4 flow for statitic
        actions = [parser.OFPActionOutput(out_port)]
        actions_back = [parser.OFPActionOutput(in_port)]
        if pkt_ipv4.proto == inet.IPPROTO_TCP:
            pkt_tcp = pkt.get_protocol(tcp.tcp)
            match = parser.OFPMatch(eth_src=pkt_ethernet.src,
                                    eth_dst=pkt_ethernet.dst,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ipv4_src=pkt_ipv4.src,
                                    ipv4_dst=pkt_ipv4.dst,
                                    ip_proto=pkt_ipv4.proto,
                                    tcp_src=pkt_tcp.src_port,
                                    tcp_dst=pkt_tcp.dst_port)
            match_back = parser.OFPMatch(eth_src=pkt_ethernet.dst,
                                         eth_dst=pkt_ethernet.src,
                                         eth_type=ether.ETH_TYPE_IP,
                                         ipv4_src=pkt_ipv4.dst,
                                         ipv4_dst=pkt_ipv4.src,
                                         ip_proto=pkt_ipv4.proto,
                                         tcp_src=pkt_tcp.dst_port,
                                         tcp_dst=pkt_tcp.src_port)
        elif pkt_ipv4.proto == inet.IPPROTO_UDP:
            pkt_udp = pkt.get_protocol(udp.udp)
            match = parser.OFPMatch(eth_src=pkt_ethernet.src,
                                    eth_dst=pkt_ethernet.dst,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ipv4_src=pkt_ipv4.src,
                                    ipv4_dst=pkt_ipv4.dst,
                                    ip_proto=pkt_ipv4.proto,
                                    udp_src=pkt_udp.src_port,
                                    udp_dst=pkt_udp.dst_port)
            match_back = parser.OFPMatch(eth_src=pkt_ethernet.dst,
                                         eth_dst=pkt_ethernet.src,
                                         eth_type=ether.ETH_TYPE_IP,
                                         ipv4_src=pkt_ipv4.dst,
                                         ipv4_dst=pkt_ipv4.src,
                                         ip_proto=pkt_ipv4.proto,
                                         udp_src=pkt_udp.dst_port,
                                         udp_dst=pkt_udp.src_port)
        else:
            match = parser.OFPMatch(eth_src=pkt_ethernet.src,
                                    eth_dst=pkt_ethernet.dst,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ipv4_src=pkt_ipv4.src,
                                    ipv4_dst=pkt_ipv4.dst)
            match_back = parser.OFPMatch(eth_src=pkt_ethernet.dst,
                                         eth_dst=pkt_ethernet.src,
                                         eth_type=ether.ETH_TYPE_IP,
                                         ipv4_src=pkt_ipv4.dst,
                                         ipv4_dst=pkt_ipv4.src)
        ofp_helper.add_flow(datapath,
                            table_id=1,
                            priority=self.service_priority,
                            match=match,
                            actions=actions,
                            idle_timeout=10)
        ofp_helper.add_flow(datapath,
                            table_id=1,
                            priority=self.service_priority,
                            match=match_back,
                            actions=actions_back,
                            idle_timeout=10)
        ofp_helper.send_packet_out(msg, in_port, actions)
Example #21
0
    def _private_to_public(self,
                           datapath,
                           buffer_id,
                           data,
                           in_port,
                           out_port,
                           pkt_ip,
                           pkt_ethernet,
                           pkt_tcp=None,
                           pkt_udp=None,
                           pkt_icmp=None):
        if pkt_ip is None:
            return

        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto

        eth_dst = pkt_ethernet.dst
        eth_src = pkt_ethernet.src
        ipv4_src = pkt_ip.src
        ipv4_dst = pkt_ip.dst

        nat_port = self._get_available_port()

        if (self._is_public(ipv4_dst)
                and not self._in_public_ip_subnetwork(ipv4_dst)):
            target_ip = self.public_gateway
        elif self._in_public_ip_subnetwork(ipv4_dst):
            target_ip = ipv4_dst
        elif self._in_private_subnetwork(ipv4_dst):
            return

        if pkt_tcp:
            # Install TCP Flow Entry
            tcp_src = pkt_tcp.src_port
            tcp_dst = pkt_tcp.dst_port
            # egress
            match = parser.OFPMatch(in_port=in_port,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ip_proto=inet.IPPROTO_TCP,
                                    ipv4_src=ipv4_src,
                                    ipv4_dst=ipv4_dst,
                                    tcp_src=tcp_src,
                                    tcp_dst=tcp_dst)
            actions = [
                parser.OFPActionSetField(eth_dst=IP_TO_MAC_TABLE[target_ip]),
                parser.OFPActionSetField(ipv4_src=self.public_ip),
                parser.OFPActionSetField(tcp_src=nat_port)
            ]
            forward_actions = [parser.OFPActionOutput(out_port)]

            # ingress
            match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                         ip_proto=inet.IPPROTO_TCP,
                                         ipv4_src=ipv4_dst,
                                         ipv4_dst=self.public_ip,
                                         tcp_src=tcp_dst,
                                         tcp_dst=nat_port)

            actions_back = [
                parser.OFPActionSetField(eth_dst=eth_src),
                parser.OFPActionSetField(ipv4_dst=ipv4_src),
                parser.OFPActionSetField(tcp_dst=tcp_src)
            ]
            forward_match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                                 ip_proto=inet.IPPROTO_TCP,
                                                 ipv4_src=ipv4_dst,
                                                 ipv4_dst=ipv4_src,
                                                 tcp_src=tcp_dst,
                                                 tcp_dst=tcp_src)
            forward_actions_back = [parser.OFPActionOutput(in_port)]

        elif pkt_udp:
            # Install UDP Flow Entry
            udp_src = pkt_udp.src_port
            udp_dst = pkt_udp.dst_port

            # egress, inside-to-outside
            match = parser.OFPMatch(in_port=in_port,
                                    eth_type=ether.ETH_TYPE_IP,
                                    ip_proto=inet.IPPROTO_UDP,
                                    ipv4_src=ipv4_src,
                                    ipv4_dst=ipv4_dst,
                                    udp_src=udp_src,
                                    udp_dst=udp_dst)
            actions = [
                parser.OFPActionSetField(eth_dst=IP_TO_MAC_TABLE[target_ip]),
                parser.OFPActionSetField(ipv4_src=self.public_ip),
                parser.OFPActionSetField(udp_src=nat_port)
            ]
            forward_actions = [parser.OFPActionOutput(out_port)]

            # ingress, outside-to-inside
            match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                         ip_proto=inet.IPPROTO_UDP,
                                         ipv4_src=ipv4_dst,
                                         ipv4_dst=self.public_ip,
                                         udp_src=udp_dst,
                                         udp_dst=nat_port)
            actions_back = [
                parser.OFPActionSetField(eth_dst=eth_src),
                parser.OFPActionSetField(ipv4_dst=ipv4_src),
                parser.OFPActionSetField(udp_dst=udp_src)
            ]

            forward_match_back = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                                 ip_proto=inet.IPPROTO_UDP,
                                                 ipv4_src=ipv4_dst,
                                                 ipv4_dst=ipv4_src,
                                                 udp_src=udp_dst,
                                                 udp_dst=udp_src)
            forward_actions_back = [parser.OFPActionOutput(in_port)]
        else:
            pass
        # outside - inside set-filed (Table 0)
        ofp_helper.add_flow_with_next(datapath,
                                      table_id=self.ingress_table_id,
                                      priority=self.service_priority,
                                      match=match_back,
                                      actions=actions_back,
                                      idle_timeout=self.IDLE_TIME)
        # inside - outside go-to-next (Table 0)
        ofp_helper.add_flow_goto_next(datapath,
                                      table_id=self.ingress_table_id,
                                      priority=self.service_priority,
                                      match=match,
                                      idle_timeout=self.IDLE_TIME)
        # outside - inside out-port (Table 3)
        ofp_helper.add_flow(datapath,
                            table_id=self.forward_table_id,
                            priority=self.service_priority,
                            match=forward_match_back,
                            actions=forward_actions_back,
                            idle_timeout=self.IDLE_TIME)
        # inside - outside write-out-port(Table 3)
        ofp_helper.add_write_flow_with_next(datapath,
                                            table_id=self.forward_table_id,
                                            priority=self.service_priority,
                                            match=match,
                                            actions=forward_actions,
                                            idle_timeout=self.IDLE_TIME)
        # inside - outside set-field( Table 4)
        ofp_helper.add_flow(datapath,
                            table_id=self.egress_table_id,
                            priority=self.service_priority,
                            match=match,
                            actions=actions,
                            idle_timeout=self.IDLE_TIME)

        # send first packet back to switch
        d = None
        if buffer_id == ofproto.OFP_NO_BUFFER:
            d = data
        out = parser.OFPPacketOut(datapath=datapath,
                                  buffer_id=buffer_id,
                                  in_port=in_port,
                                  actions=actions,
                                  data=d)
        datapath.send_msg(out)