Beispiel #1
0
    def __init__(self, id, config, logger):
        # participant id
        self.id = id
        # print ID for logging
        self.logger = logger

        # used to signal termination
        self.run = True
        self.prefix_lock = {}
        self.arp_table = {}

        # Initialize participant params
        self.cfg = PConfig(config, self.id)
        # Vmac encoding mode
        # self.cfg.vmac_mode = config_file["vmac_mode"]
        # Dataplane mode---multi table or multi switch
        # self.cfg.dp_mode = config_file["dp_mode"]

        self.policies = self.cfg.config["Policies"]

        # The port 0 MAC is used for tagging outbound rules as belonging to us
        self.port0_mac = self.cfg.port0_mac

        self.nexthop_2_part = self.cfg.config["Next Hops"]

        # VNHs related params
        self.num_VNHs_in_use = 0
        self.VNH_2_prefix = {}
        self.prefix_2_VNH = {}

        # Keeps track of the current participant that is the default next hop for VNHs
        self.nhpart_2_VNHs = {}

        # Superset related params
        if self.cfg.isSupersetsMode():
            self.supersets = SuperSets(self, self.cfg.vmac_options)
        else:
            # TODO: create similar class and variables for MDS
            self.mds = None

        # Keep track of flow rules pushed
        self.dp_pushed = []
        # Keep track of flow rules which are scheduled to be pushed
        self.dp_queued = []

        self.bgp_instance = BGPPeer(id, self.cfg.asn, self.cfg.ports,
                                    self.cfg.peers_in, self.cfg.peers_out)

        self.fm_builder = FlowModMsgBuilder(self.id)
Beispiel #2
0
class GSSmT(GSS):
    def __init__(self, sender, config, vmac_builder):
        super(GSSmT, self).__init__(sender, config, vmac_builder)
        self.logger = logging.getLogger('GSSmT')
        self.fm_builder = FlowModMsgBuilder()

    def start(self):
        self.logger.info('start')
        self.init_fabric()

    def init_fabric(self):
        self.logger.info('init fabric')

        # MAIN-IN TABLE
        # handle BGP traffic
        self.logger.info('create flow mods to handle BGP traffic')
        self.handle_bgp("main-in")

        # handle ARP traffic
        self.logger.info('create flow mods to handle ARP traffic')
        self.handle_arp("main-in")

        # tag participant packets
        self.logger.info('create flow mods to handle participant traffic')
        self.tagging("main-in")

        # whatever doesn't match on any other rule, send to outbound switch
        self.match_any_fwd("main-in", "outbound")

        # OUTBOUND SWITCH
        # whatever doesn't match on any other rule, send to inbound switch
        self.match_any_fwd("outbound", "inbound")

        # INBOUND SWITCH
        # send all other packets to main
        self.match_any_fwd("inbound", "main-out")

        # MAIN-OUT TABLE
        # default forwarding
        self.default_forwarding("main-out")

        self.sender.send(self.fm_builder.get_msg())

        self.logger.info('sent flow mods to reference monitor')
Beispiel #3
0
 def __init__(self, logger, sender, config):
     self.logger = logger
     self.sender = sender
     self.config = config
     self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])
     self.vmac_builder = VMACBuilder(self.config.vmac_options)
Beispiel #4
0
class GSS(object):
    def __init__(self, logger, sender, config):
        self.logger = logger
        self.sender = sender
        self.config = config
        self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])
        self.vmac_builder = VMACBuilder(self.config.vmac_options)

    def handle_BGP(self, rule_type):
        ### BGP traffic to route server
        port = self.config.route_server.ports[0]
	self.logger.debug("JEROENDEBUG-----------" + str(port))
        action = {"fwd": [port.id]}
        match = {"eth_dst": port.mac, "tcp_src": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

        match = {"eth_dst": port.mac, "tcp_dst": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

        ### BGP traffic to participants
        for participant in self.config.peers.values():
            for port in participant.ports:
                match = {"eth_dst": port.mac, "tcp_src": BGP}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
                match = {"eth_dst": port.mac, "tcp_dst": BGP}
                self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

    def handle_ARP_in_main(self, rule_type):
        ### direct all ARP responses for the route server to it
        port = self.config.route_server.ports[0]
        match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

        for participant in self.config.peers.values():
            ### make sure ARP replies reach the participants
            for port in participant.ports:
                match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

            ### direct gratuituous ARPs only to the respective participant
            i = 0
            for port in participant.ports:
                vmac = self.vmac_builder.part_port_match(participant.name, i, inbound_bit = False)
                vmac_mask = self.vmac_builder.part_port_mask(False)
                match = {"in_port": "arp",
                         "eth_type": ETH_TYPE_ARP,
                         "eth_dst": (vmac, vmac_mask)}
                action = {"set_eth_dst": MAC_BROADCAST, "fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)
                i += 1

        ### flood ARP requests that have gone through the arp switch, but only on non switch-switch ports
        match = {"in_port": "arp",
                 "eth_type": ETH_TYPE_ARP,
                 "eth_dst": MAC_BROADCAST}
        ports = []
        for participant in self.config.peers.values():
            for port in participant.ports:
                ports.append(port.id)
        ports.append(self.config.route_server.ports[0].id)

        action = {"fwd": ports}
        self.fm_builder.add_flow_mod("insert", rule_type, ARP_BROADCAST_PRIORITY, match, action)

        ### forward all ARP requests to the arp switch
        match = {"eth_type": ETH_TYPE_ARP}
        action = {"fwd": ["arp"]}
        self.fm_builder.add_flow_mod("insert", rule_type, VNH_ARP_FILTER_PRIORITY, match, action)

    def handle_ARP_in_arp(self, rule_type):
        ### direct ARP requests for VNHs to ARP proxy
        port = self.config.arp_proxy.ports[0]
        match = {"in_port": "main",
                 "eth_type": ETH_TYPE_ARP,
                 "arp_tpa": (str(self.config.vnhs.network), str(self.config.vnhs.netmask))}
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, VNH_ARP_PRIORITY, match, action)

        ### send all other ARP requests back
        match = {"eth_type": ETH_TYPE_ARP, "in_port": "main"}
        action = {"fwd": [OFPP_IN_PORT]}
        self.fm_builder.add_flow_mod("insert", rule_type, DEFAULT_PRIORITY, match, action)

        ### send all ARP replies from the ARP proxy to the main switch
        match = {"eth_type": ETH_TYPE_ARP, "in_port": "arp proxy"}
        action = {"fwd": ["main"]}
        self.fm_builder.add_flow_mod("insert", rule_type, DEFAULT_PRIORITY, match, action)

    def handle_participant_with_outbound(self, rule_type):
        for participant in self.config.peers.values():
            ### outbound policies specified
            if participant.outbound_rules:
                mac = None
                for port in participant.ports:
                    if mac is None:
                        mac = port.mac
                    match = {"in_port": port.id}
                    action = {"set_eth_src": mac, "fwd": ["outbound"]}
                    self.fm_builder.add_flow_mod("insert", rule_type, OUTBOUND_PRIORITY, match, action)

    def handle_participant_with_inbound(self, rule_type, mask_inbound_bit):
        for participant in self.config.peers.values():
            ### inbound policies specified
            if participant.inbound_rules:
                i = 0
                for port in participant.ports:
                    vmac = self.vmac_builder.part_port_match(participant.name, i, False)
                    i += 1
                    vmac_mask = self.vmac_builder.part_port_mask(mask_inbound_bit)
                    match = {"eth_dst": (vmac, vmac_mask)}
                    action = {"set_eth_dst": port.mac,
                              "fwd": [port.id]}
                    self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)

    def default_forwarding(self, rule_type):
        for participant in self.config.peers.values():
            ### default forwarding
            if not participant.inbound_rules:
                vmac = self.vmac_builder.next_hop_match(participant.name, False)
                vmac_mask = self.vmac_builder.next_hop_mask(False)
                port = participant.ports[0]
                match = {"eth_dst": (vmac, vmac_mask)}
                action = {"set_eth_dst": port.mac,
                          "fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)

    def default_forwarding_inbound(self, rule_type, fwd):
        ## set the inbound bit to zero
        for participant in self.config.peers.values():
            if participant.inbound_rules:
                port = participant.ports[0]
                vmac_match = self.vmac_builder.next_hop_match(participant.name, False)
                vmac_match_mask = self.vmac_builder.next_hop_mask(False)
                vmac_action = self.vmac_builder.part_port_match(participant.name, 0, False)
                match = {"eth_dst": (vmac_match, vmac_match_mask)}
                action = {"set_eth_dst": vmac_action, "fwd": [fwd]}
                self.fm_builder.add_flow_mod("insert", "inbound", INBOUND_PRIORITY, match, action)

    def handle_inbound(self, rule_type):
        vmac = self.vmac_builder.only_first_bit()
        match = {"eth_dst": (vmac, vmac)}
        action = {"fwd": ["outbound"]}
        self.fm_builder.add_flow_mod("insert", rule_type, INBOUND_BIT_PRIORITY, match, action)

    def match_any_fwd(self, rule_type, dst):
        match = {}
        action = {"fwd": [dst]}
        self.fm_builder.add_flow_mod("insert", rule_type, DEFAULT_PRIORITY, match, action)

    def delete_flow_rule(self, rule_type, cookie, cookie_mask):
        self.fm_builder.delete_flow_mod("remove", rule_type, cookie, cookie_mask)

    def start(self):
        self.logger.info('start')
        self.init_fabric()
        self.sender.send(self.fm_builder.get_msg())
        self.logger.info('sent flow mods to reference monitor')
Beispiel #5
0
 def __init__(self, logger, sender, config):
     self.logger = logger
     self.sender = sender
     self.config = config
     self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])
     self.vmac_builder = VMACBuilder(self.config.vmac_options)
Beispiel #6
0
class GSS(object):
    def __init__(self, logger, sender, config):
        self.logger = logger
        self.sender = sender
        self.config = config
        self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])
        self.vmac_builder = VMACBuilder(self.config.vmac_options)

    def handle_BGP(self, rule_type):
        ### BGP traffic to route server
        port = self.config.route_server.ports[0]
        action = {"fwd": [port.id]}
        match = {"eth_dst": port.mac, "tcp_src": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, "bgp", match, action)

        match = {"eth_dst": port.mac, "tcp_dst": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, "bgp", match, action)

        ### BGP traffic to participants
        for participant in self.config.peers.values():
            for port in participant.ports:
                match = {"eth_dst": port.mac, "tcp_src": BGP}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, "bgp", match,
                                             action)
                match = {"eth_dst": port.mac, "tcp_dst": BGP}
                self.fm_builder.add_flow_mod("insert", rule_type, "bgp", match,
                                             action)

    def handle_ARP_in_main(self, rule_type):
        ### direct all ARP responses for the route server to it
        port = self.config.route_server.ports[0]
        match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, "arp", match, action)

        for participant in self.config.peers.values():
            ### make sure ARP replies reach the participants
            for port in participant.ports:
                match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, "arp", match,
                                             action)

            ### direct gratuituous ARPs only to the respective participant
            i = 0
            for port in participant.ports:
                vmac = self.vmac_builder.part_port_match(participant.name,
                                                         i,
                                                         inbound_bit=False)
                vmac_mask = self.vmac_builder.part_port_mask(False)
                match = {
                    "in_port": "arp",
                    "eth_type": ETH_TYPE_ARP,
                    "eth_dst": (vmac, vmac_mask)
                }
                action = {"set_eth_dst": MAC_BROADCAST, "fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, "arp", match,
                                             action)
                i += 1

        ### flood ARP requests that have gone through the arp switch, but only on non switch-switch ports
        match = {
            "in_port": "arp",
            "eth_type": ETH_TYPE_ARP,
            "eth_dst": MAC_BROADCAST
        }
        ports = []
        for participant in self.config.peers.values():
            for port in participant.ports:
                ports.append(port.id)
        ports.append(self.config.route_server.ports[0].id)

        action = {"fwd": ports}
        self.fm_builder.add_flow_mod("insert", rule_type, "arp_broadcast",
                                     match, action)

        ### forward all ARP requests to the arp switch
        match = {"eth_type": ETH_TYPE_ARP}
        action = {"fwd": ["arp"]}
        self.fm_builder.add_flow_mod("insert", rule_type, "arp_filter", match,
                                     action)

    def handle_ARP_in_arp(self, rule_type):
        ### direct ARP requests for VNHs to ARP proxy
        port = self.config.arp_proxy.ports[0]
        match = {
            "in_port":
            "main",
            "eth_type":
            ETH_TYPE_ARP,
            "arp_tpa":
            (str(self.config.vnhs.network), str(self.config.vnhs.netmask))
        }
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, "vnh_arp", match,
                                     action)

        ### send all other ARP requests back
        match = {"eth_type": ETH_TYPE_ARP, "in_port": "main"}
        action = {"fwd": [OFPP_IN_PORT]}
        self.fm_builder.add_flow_mod("insert", rule_type, "default", match,
                                     action)

        ### send all ARP replies from the ARP proxy to the main switch
        match = {"eth_type": ETH_TYPE_ARP, "in_port": "arp proxy"}
        action = {"fwd": ["main"]}
        self.fm_builder.add_flow_mod("insert", rule_type, "default", match,
                                     action)

    def handle_participant_with_outbound(self, rule_type):
        for participant in self.config.peers.values():
            ### outbound policies specified
            if participant.outbound_rules:
                mac = None
                for port in participant.ports:
                    if mac is None:
                        mac = port.mac
                    match = {"in_port": port.id}
                    action = {"set_eth_src": mac, "fwd": ["outbound"]}
                    self.fm_builder.add_flow_mod("insert", rule_type,
                                                 "outbound", match, action)

    def handle_participant_with_inbound(self, rule_type, mask_inbound_bit):
        for participant in self.config.peers.values():
            ### inbound policies specified
            if participant.inbound_rules:
                i = 0
                for port in participant.ports:
                    vmac = self.vmac_builder.part_port_match(
                        participant.name, i, False)
                    i += 1
                    vmac_mask = self.vmac_builder.part_port_mask(
                        mask_inbound_bit)
                    match = {"eth_dst": (vmac, vmac_mask)}
                    action = {"set_eth_dst": port.mac, "fwd": [port.id]}
                    self.fm_builder.add_flow_mod("insert", rule_type, "output",
                                                 match, action)

    def default_forwarding(self, rule_type):
        for participant in self.config.peers.values():
            ### default forwarding
            if not participant.inbound_rules:
                vmac = self.vmac_builder.next_hop_match(
                    participant.name, False)
                vmac_mask = self.vmac_builder.next_hop_mask(False)
                port = participant.ports[0]
                print "VMAC default rule match:", (vmac, vmac_mask)
                match = {"eth_dst": (vmac, vmac_mask)}
                action = {"set_eth_dst": port.mac, "fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, "output",
                                             match, action)

    def default_forwarding_inbound(self, rule_type, fwd):
        ## set the inbound bit to zero
        for participant in self.config.peers.values():
            if participant.inbound_rules:
                port = participant.ports[0]
                vmac_match = self.vmac_builder.next_hop_match(
                    participant.name, False)
                vmac_match_mask = self.vmac_builder.next_hop_mask(False)
                vmac_action = self.vmac_builder.part_port_match(
                    participant.name, 0, False)
                print "VMAC default rule match:", (vmac_match, vmac_match_mask)
                match = {"eth_dst": (vmac_match, vmac_match_mask)}
                action = {"set_eth_dst": vmac_action, "fwd": [fwd]}
                self.fm_builder.add_flow_mod("insert", "inbound", "inbound",
                                             match, action)

    def handle_inbound(self, rule_type):
        vmac = self.vmac_builder.only_first_bit()
        match = {"eth_dst": (vmac, vmac)}
        action = {"fwd": ["outbound"]}
        self.fm_builder.add_flow_mod("insert", rule_type, "inbound", match,
                                     action)

    def match_any_fwd(self, rule_type, dst):
        match = {}
        action = {"fwd": [dst]}
        self.fm_builder.add_flow_mod("insert", rule_type, "default", match,
                                     action)

    def delete_flow_rule(self, rule_type, cookie, cookie_mask):
        self.fm_builder.delete_flow_mod("remove", rule_type, cookie,
                                        cookie_mask)

    def start(self):
        self.logger.info('start')
        self.init_fabric()
        self.sender.send(self.fm_builder.get_msg())
        self.logger.info('sent flow mods to reference monitor')
Beispiel #7
0
class PCtrl(object):
    def __init__(self, id, config, logger):
        # participant id
        self.id = id
        # print ID for logging
        self.logger = logger

        # used to signal termination
        self.run = True
        self.prefix_lock = {}
        self.arp_table = {}

        # Initialize participant params
        self.cfg = PConfig(config, self.id)
        # Vmac encoding mode
        # self.cfg.vmac_mode = config_file["vmac_mode"]
        # Dataplane mode---multi table or multi switch
        # self.cfg.dp_mode = config_file["dp_mode"]

        self.policies = self.cfg.config["Policies"]

        # The port 0 MAC is used for tagging outbound rules as belonging to us
        self.port0_mac = self.cfg.port0_mac

        self.nexthop_2_part = self.cfg.config["Next Hops"]

        # VNHs related params
        self.num_VNHs_in_use = 0
        self.VNH_2_prefix = {}
        self.prefix_2_VNH = {}

        # Keeps track of the current participant that is the default next hop for VNHs
        self.nhpart_2_VNHs = {}

        # Superset related params
        if self.cfg.isSupersetsMode():
            self.supersets = SuperSets(self, self.cfg.vmac_options)
        else:
            # TODO: create similar class and variables for MDS
            self.mds = None

        # Keep track of flow rules pushed
        self.dp_pushed = []
        # Keep track of flow rules which are scheduled to be pushed
        self.dp_queued = []

        self.bgp_instance = BGPPeer(id, self.cfg.asn, self.cfg.ports,
                                    self.cfg.peers_in, self.cfg.peers_out)

        self.fm_builder = FlowModMsgBuilder(self.id)

    def sanitize_policies(self, policies):

        port_count = len(self.cfg.ports)

        # sanitize the input policies
        if 'inbound' in policies:
            for policy in policies['inbound']:
                if 'action' not in policy:
                    continue
                if 'fwd' in policy['action'] and int(
                        policy['action']['fwd']) >= port_count:
                    policy['action']['fwd'] = 0

        return policies

    def load_policies(self, policy_file):
        # Load policies from file

        with open(policy_file, 'r') as f:
            policies = json.load(f)

        return self.sanitize_policies(policies)

    def initialize_dataplane(self):
        "Read the config file and update the queued policy variable"

        self.logger.info("Initializing inbound rules")

        final_switch = "main-in"
        if self.cfg.isMultiTableMode() or self.cfg.isMultiHopMode():
            final_switch = "main-out"

        self.init_vnh_assignment()

        rule_msgs = init_inbound_rules(self.id, self.policies, self.supersets,
                                       final_switch)
        self.logger.debug("Rule Messages INBOUND:: " + str(rule_msgs))

        rule_msgs2 = init_outbound_rules(self, self.id, self.policies,
                                         self.supersets, final_switch)
        self.logger.debug("Rule Messages OUTBOUND:: " + str(rule_msgs2))

        if 'changes' in rule_msgs2:
            if 'changes' not in rule_msgs:
                rule_msgs['changes'] = []
            rule_msgs['changes'] += rule_msgs2['changes']

        #TODO: Initialize Outbound Policies from RIB
        self.logger.debug("Rule Messages:: " + str(rule_msgs))
        if 'changes' in rule_msgs:
            self.dp_queued.extend(rule_msgs["changes"])

    def push_dp(self):
        '''
        (1) Check if there are any policies queued to be pushed
        (2) Send the queued policies to reference monitor
        '''

        # it is crucial that dp_queued is traversed chronologically
        for flowmod in self.dp_queued:
            self.fm_builder.add_flow_mod(**flowmod)
            self.dp_pushed.append(flowmod)

        # reset queue
        self.dp_queued = []

        flows = self.fm_builder.get_msg()

        self.fm_builder.reset_flow_mod()

        return flows

        # reset flow_mods after send - self.flow_mods = []

    def process_event(self, data, mod_type=None):
        "Locally process each incoming network event"

        if 'bgp' in data:
            self.logger.debug("Event Received: BGP Update.")
            route = data['bgp']
            # Process the incoming BGP updates from XRS
            #self.logger.debug("BGP Route received: "+str(route)+" "+str(type(route)))
            return self.process_bgp_route(route)

        elif 'policy' in data:
            # Process the event requesting change of participants' policies
            self.logger.debug("Event Received: Policy change.")
            change_info = data['policy']
            for element in change_info:
                if 'remove' in element:
                    self.process_policy_changes(element['remove'], 'remove')
                    #self.logger.debug("PART_Test: REMOVE: %s" % element)
                if 'insert' in element:
                    self.process_policy_changes(element['insert'], 'insert')
                    #self.logger.debug("PART_Test: INSERT: %s" % element)

        elif 'arp' in data:
            if data['arp'] == 1:
                ip = data['SPA']
                mac = data['SHA']
                part = data['participant']
                if part not in self.nhpart_2_VNHs:
                    self.nhpart_2_VNHs[part] = []

                if ip not in self.nhpart_2_VNHs[part]:
                    self.nhpart_2_VNHs[part].append(ip)
                newbest = (part, mac)
                if ip not in self.arp_table:
                    self.arp_table[ip] = ARPEntry(newbest, None)
                else:
                    ae = self.arp_table[ip]
                    # Modify only if it is an actual change
                    if self.arp_table[ip].best_hop != newbest:
                        self.arp_table[ip] = ARPEntry(newbest, ae.best_hop)
            else:
                (requester_srcmac, requested_vnh) = tuple(data['arp'])
                self.logger.debug("Event Received: ARP request for IP " +
                                  str(requested_vnh))
                self.process_arp_request(requester_srcmac, requested_vnh)

        else:
            self.logger.warn("UNKNOWN EVENT TYPE RECEIVED: " + str(data))

    def process_message(self, msg):
        mtype = msg["msg_type"]
        if mtype == "linkdown":
            part = msg["participant"]
            if part not in self.nhpart_2_VNHs:
                return
            vnhs = self.nhpart_2_VNHs[part]
            for v in vnhs:
                best = self.arp_table[v].best_hop
                second = self.arp_table[v].prev_hop
                if part == best[0] and second:
                    # Send ARP with available second best-hop
                    for port in self.cfg.ports:
                        self.process_arp_request(port["MAC"], v, second[1])

    def process_policy_changes(self, change_info, mod_type):
        # idea to remove flow rules for the old policies with cookies
        '''
        removal_msgs = []
        for element in change_info:

            if 'removal_cookies' in element:
        
                for cookie in element['removal_cookies']:
                    cookie_id = (cookie['cookie'],65535)
                    match_args = cookie['match']
                    mod =  {"rule_type":"inbound", "priority":4,"match":{} , "action":{}, "cookie":cookie_id, "mod_type":"remove"}
                    removal_msgs.append(mod)
        
        self.dp_queued.extend(removal_msgs)
        '''

        # json file format for change_info - mod_type = remove or insert
        '''
        {
            "policy": [
            {
                mod_type: [ 
        
        # change_info begin

                    {
                        "inbound": [
                            { cookie1 ... match ... action }
                            { cookie2 ... match ... action }
                        ]
                    }

                    {
                        "outbound": [
                            { cookie1 ... match ... action }
                            { cookie2 ... match ... action }
                        ]
                    }

        # change_info end
                
                ]           // end mod_type-array
            }, 
            
            {
                mod_type: ...

            }

            ]               // end policy-array
        }
        '''

        policies = self.sanitize_policies(change_info)

        final_switch = "main-in"
        if self.cfg.isMultiTableMode():
            final_switch = "main-out"

        #self.init_vnh_assignment() // not used
        inbound_policies = {}
        outbound_policies = {}

        for element in policies:
            if 'inbound' in element:
                inbound_policies = element
            if 'outbound' in element:
                outbound_policies = element

        #self.logger.debug("PART_Test: INBOUND: %s" % inbound_policies)
        #self.logger.debug("PART_Test: OUTBOUND: %s" % outbound_policies)

        rule_msgs = init_inbound_rules(self.id, inbound_policies,
                                       self.supersets, final_switch)

        rule_msgs2 = init_outbound_rules(self, self.id, outbound_policies,
                                         self.supersets, final_switch)

        if 'changes' in rule_msgs2:
            if 'changes' not in rule_msgs:
                rule_msgs['changes'] = []
            rule_msgs['changes'] += rule_msgs2['changes']

        for rule in rule_msgs['changes']:
            rule['mod_type'] = mod_type

        #self.logger.debug("PART_Test: Rule Msgs: %s" % rule_msgs)

        if 'changes' in rule_msgs:
            self.dp_queued.extend(rule_msgs["changes"])

        self.push_dp()

    def process_bgp_route(self, route):
        "Process each incoming BGP advertisement"
        tstart = time.time()

        # Map to update for each prefix in the route advertisement.
        updates = self.bgp_instance.update(route)
        #self.logger.debug("process_bgp_route:: "+str(updates))
        # TODO: This step should be parallelized
        # TODO: The decision process for these prefixes is going to be same, we
        # should think about getting rid of such redundant computations.
        for update in updates:
            self.bgp_instance.decision_process_local(update)
            self.vnh_assignment(update)

        if TIMING:
            elapsed = time.time() - tstart
            self.logger.debug("Time taken for decision process: " +
                              str(elapsed))
            tstart = time.time()

        if self.cfg.isSupersetsMode():
            ################## SUPERSET RESPONSE TO BGP ##################
            # update supersets
            "Map the set of BGP updates to a list of superset expansions."
            ss_changes, ss_changed_prefs = self.supersets.update_supersets(
                self, updates)

            if TIMING:
                elapsed = time.time() - tstart
                self.logger.debug("Time taken to update supersets: " +
                                  str(elapsed))
                tstart = time.time()

            # ss_changed_prefs are prefixes for which the VMAC bits have changed
            # these prefixes must have gratuitous arps sent
            garp_required_vnhs = [
                self.prefix_2_VNH[prefix] for prefix in ss_changed_prefs
            ]

            "If a recomputation event was needed, wipe out the flow rules."
            if ss_changes["type"] == "new":
                self.logger.debug("Wiping outbound rules.")
                wipe_msgs = msg_clear_all_outbound(self.policies,
                                                   self.port0_mac)
                self.dp_queued.extend(wipe_msgs)

                #if a recomputation was needed, all VMACs must be reARPed
                # TODO: confirm reARPed is a word
                garp_required_vnhs = self.VNH_2_prefix.keys()

            if len(ss_changes['changes']) > 0:

                self.logger.debug("Supersets have changed: " + str(ss_changes))

                "Map the superset changes to a list of new flow rules."
                flow_msgs = update_outbound_rules(ss_changes, self.policies,
                                                  self.supersets,
                                                  self.port0_mac)

                self.logger.debug("Flow msgs: " + str(flow_msgs))
                "Dump the new rules into the dataplane queue."
                self.dp_queued.extend(flow_msgs)

            if TIMING:
                elapsed = time.time() - tstart
                self.logger.debug("Time taken to deal with ss_changes: " +
                                  str(elapsed))
                tstart = time.time()

        ################## END SUPERSET RESPONSE ##################

        else:
            # TODO: similar logic for MDS
            self.logger.debug("Creating ctrlr messages for MDS scheme")

        if TIMING:
            elapsed = time.time() - tstart
            self.logger.debug("Time taken to push dp msgs: " + str(elapsed))
            tstart = time.time()

        changed_vnhs, announcements = self.bgp_instance.bgp_update_peers(
            updates, self.prefix_2_VNH, self.cfg.ports)
        """ Combine the VNHs which have changed BGP default routes with the
            VNHs which have changed supersets.
        """

        changed_vnhs = set(changed_vnhs)
        changed_vnhs.update(garp_required_vnhs)

        # Send gratuitous ARP responses for all them
        # for vnh in changed_vnhs:
        #     self.process_arp_request(None, vnh)

        # Tell Route Server that it needs to announce these routes
        # for announcement in announcements:
        #     # TODO: Complete the logic for this function
        #     self.send_announcement(announcement)

        if TIMING:
            elapsed = time.time() - tstart
            self.logger.debug("Time taken to send garps/announcements: " +
                              str(elapsed))
            tstart = time.time()

        return self.push_dp()

    def vnh_assignment(self, update):
        "Assign VNHs for the advertised prefixes"
        if self.cfg.isSupersetsMode():
            " Superset"
            # TODO: Do we really need to assign a VNH for each advertised prefix?
            if ('announce' in update):
                prefix = update['announce'].prefix

                if (prefix not in self.prefix_2_VNH):
                    # get next VNH and assign it the prefix
                    self.num_VNHs_in_use += 1
                    vnh = str(self.cfg.VNHs[self.num_VNHs_in_use])

                    self.prefix_2_VNH[prefix] = vnh
                    self.VNH_2_prefix[vnh] = prefix
        else:
            "Disjoint"
            # TODO: @Robert: Place your logic here for VNH assignment for MDS scheme
            self.logger.debug("VNH assignment called for disjoint vmac_mode")

    def init_vnh_assignment(self):
        "Assign VNHs for the advertised prefixes"
        if self.cfg.isSupersetsMode():
            " Superset"
            # TODO: Do we really need to assign a VNH for each advertised prefix?
            #self.bgp_instance.rib["local"].dump()
            prefixes = self.bgp_instance.rib.get_local_prefixes()
            #print 'init_vnh_assignment: prefixes:', prefixes
            #print 'init_vnh_assignment: prefix_2_VNH:', self.prefix_2_VNH
            for prefix in prefixes:
                if (prefix not in self.prefix_2_VNH):
                    # get next VNH and assign it the prefix
                    self.num_VNHs_in_use += 1
                    vnh = str(self.cfg.VNHs[self.num_VNHs_in_use])

                    self.prefix_2_VNH[prefix] = vnh
                    self.VNH_2_prefix[vnh] = prefix
        else:
            "Disjoint"
            # TODO: @Robert: Place your logic here for VNH assignment for MDS scheme
            self.logger.debug("VNH assignment called for disjoint vmac_mode")
Beispiel #8
0
class MDS(object):
    def __init__(self, logger, sender, config):
        self.logger = logger
        self.sender = sender
        self.config = config
        self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])

    def handle_BGP(self, rule_type):
        ### BGP traffic to route server
        port = self.config.route_server.ports[0]
        action = {"fwd": [port.id]}
        match = {"eth_dst": port.mac, "tcp_src": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

        match = {"eth_dst": port.mac, "tcp_dst": BGP}
        self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

        ### BGP traffic to participants
        for participant in self.config.peers.values():
            for port in participant.ports:
                match = {"eth_dst": port.mac, "tcp_src": BGP}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
                match = {"eth_dst": port.mac, "tcp_dst": BGP}
                self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)

    def handle_ARP(self, rule_type):
        ### direct ARP requests for VNHs to ARP proxy
        port = self.config.arp_proxy.ports[0]
        match = {"eth_type": ETH_TYPE_ARP, "arp_tpa": (str(self.config.vnhs.network), str(self.config.vnhs.netmask))}
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

        ### direct all ARP requests for the route server to it
        port = self.config.route_server.ports[0]
        match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
        action = {"fwd": [port.id]}
        self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

        for participant in self.config.peers.values():
            ### make sure ARP replies reach the participants
            for port in participant.ports:
                match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

        ### flood ARP requests
        match = {"eth_type": ETH_TYPE_ARP, "eth_dst": MAC_BROADCAST}

        ports = []
        for participant in self.config.peers.values():
            for port in participant.ports:
                ports.append(port.id)
        ports.append(self.config.arp_proxy.ports[0].id)
        ports.append(self.config.route_server.ports[0].id)

        action = {"fwd": ports}
        self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)

    def handle_participant_with_outbound(self, rule_type):
        for participant in self.config.peers.values():
            ### outbound policies specified
            if participant.outbound_rules:
                mac = None
                for port in participant.ports:
                    if mac is None:
                        mac = port.mac
                    match = {"in_port": port.id}
                    action = {"set_eth_src": mac, "fwd": ["outbound"]}
                    self.fm_builder.add_flow_mod("insert", rule_type, OUTBOUND_PRIORITY, match, action)

    def handle_participant_with_inbound(self, rule_type):
        for participant in self.config.peers.values():
            ### send all traffic for participants with inbound policies to inbound handler
            if participant.inbound_rules:
                for port in participant.ports:
                    match = {"eth_dst": port.mac}
                    action = {"fwd": ["inbound"]}
                    self.fm_builder.add_flow_mod("insert", rule_type, INBOUND_PRIORITY, match, action)

    def default_forwarding(self, rule_type):
        for participant in self.config.peers.values():
            ### default forwarding
            if not participant.inbound_rules:
                port = participant.ports[0]
                match = {"eth_dst": port.mac}
                action = {"fwd": [port.id]}
                self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)

    def default_forwarding_inbound(self, rule_type, in_port):
        ### default forwarding for traffic to participants with inbound policies
        for participant in self.config.peers.values():
            if participant.inbound_rules:
                for port in participant.ports:
                    match = {"eth_dst": port.mac}
                    if in_port:
                        match["in_port"] = 1
                    action = {"fwd": [port.id]}
                    self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)

    def match_any_fwd(self, rule_type, dst):
        match = {}
        action = {"fwd": [dst]}
        self.fm_builder.add_flow_mod("insert", rule_type, DEFAULT_PRIORITY, match, action)

    def start(self):
        self.logger.info('start')
        self.init_fabric()
        self.sender.send(self.fm_builder.get_msg())
        self.logger.info('sent flow mods to reference monitor')
Beispiel #9
0
 def __init__(self, sender, config, vmac_builder):
     super(GSSmT, self).__init__(sender, config, vmac_builder)
     self.logger = logging.getLogger('GSSmT')
     self.fm_builder = FlowModMsgBuilder()