Exemple #1
0
def _parse_snoop_status(is_igmp, vlan_id, data, vlan_name, event_data):

    ret = True
    event_data.update({'vlan-id': vlan_id, 'enable': data})

    ret = snoop_update_vlan_rules(is_igmp, vlan_name, data)
    if ret is False:
        mcast_utils.log_err(
            'Failed to %s ebtable snooping rules in kernel for %s ' %
            ("Add" if data == 1 else "Remove", vlan_name))
        return False

    mcast_utils.log_info('%s ebtable snooping rules in kernel for %s success' %
                         ("Add" if data == 1 else "Remove", vlan_name))

    # Disable snooping in kernel.
    ret = mcast_utils._update_file_system(
        mcast_utils._get_path_per_vlan_configs(vlan_name,
                                               "multicast_snooping"), 0)
    if ret is False:
        #When VLAN/bridge gets created,snooping will be disabled, this is just extra .
        mcast_utils.log_debug('Failed to disable snooping on %s in kernel' %
                              (vlan_name))

    return True
Exemple #2
0
def _parse_mcast_snoop_updates_and_publish(data, vlan_info, vlan_id,
                                           igmp_events, op):

    #Parse status, mrouter and route update and publish.
    vlan_name = vlan_info['cps/key_data']['if/interfaces/interface/name']
    try:
        for k in _snoop_obj_info:
            for path in _snoop_obj_info[k]['obj_path']:
                if path in data and _snoop_obj_info[k]['publish_events']:
                    # Publish CPS Events if required
                    event_data = {}
                    mcast_utils.log_info(
                        '%s %s %s for VLAN %d' %
                        ('IGMP' if igmp_events else 'MLD',
                         _snoop_obj_info[k]['event_string'], op, vlan_id))
                    if (k == 'static_l2_mcast_grp_key'):
                        if (_parse_snoop_routes(vlan_id, vlan_info, op,
                                                igmp_events, data[path],
                                                event_data)) is False:
                            return False
                    elif (k == 'static_mrouter_key'):
                        if (_parse_snoop_mrouter_ports(vlan_id, vlan_info, op,
                                                       data[path],
                                                       event_data)) is False:
                            return False
                    elif (k == 'mcast_snooping'):
                        if (_parse_snoop_status(igmp_events, vlan_id,
                                                data[path], vlan_name,
                                                event_data)) is False:
                            return False

                    obj = events.MCast_CpsEvents()
                    if event_data:
                        if igmp_events:
                            obj.publish_igmp_events(event_data, op)
                        else:
                            obj.publish_mld_events(event_data, op)

                        mcast_utils.log_info(
                            "Publishing %s %s %s event" %
                            (('IGMP ' if igmp_events else 'MLD '),
                             _snoop_obj_info[k]['event_string'], op))
                        mcast_utils.log_debug("Publish event data: %s" %
                                              (str(event_data)))

    except Exception as e:
        mcast_utils.log_err('Exception: %s' % e)

    return True
Exemple #3
0
def handle_snoop_updates(params):

    #This handles only the IGMP/MLD snooping "status", "mrouter port" and "route" updates.
    #This gets called only when kernel snooping functionality is not used and some snooping
    #application is running. This parses and publishes and does not set/update kernel for mrouter
    # and route updates.
    ret = True
    data = mcast_utils.cps_convert_attr_data(params['change'])

    mcast_utils.log_debug("Data: %s" % (str(data)))

    if mcast_utils.igmp_global_enable_key in data:
        return snoop_update_global_rules(
            True, data[mcast_utils.igmp_global_enable_key])
    elif mcast_utils.mld_global_enable_key in data:
        return snoop_update_global_rules(
            False, data[mcast_utils.mld_global_enable_key])

    if mcast_utils._keys['vlan_id_key'][
            'igmp'] not in data and mcast_utils._keys['vlan_id_key'][
                'mld'] not in data:
        mcast_utils.log_err("Missing VLAN ID")
        return False

    igmp_events = True
    if mcast_utils._keys['vlan_id_key']['igmp'] in data:
        vlan_id_key = mcast_utils._keys['vlan_id_key']['igmp']
    else:
        vlan_id_key = mcast_utils._keys['vlan_id_key']['mld']
        igmp_events = False

    vlan_id = data[vlan_id_key]

    mcast_utils.log_debug('%s Snoop update received for VLAN  %d' %
                          ('IGMP' if igmp_events else 'MLD', vlan_id))
    # Get dell-base-if-cmn/if/interfaces/interface object for the given vlan id
    vlan_info_list = mcast_utils._get_vlan_info(vlan_id)
    if vlan_info_list is None or len(vlan_info_list) == 0:
        mcast_utils.log_err('No VLAN Information for VLAN id %d' % vlan_id)
        return False
    vlan_info = vlan_info_list[0]

    ret = _parse_mcast_snoop_updates_and_publish(data, vlan_info, vlan_id,
                                                 igmp_events,
                                                 params['operation'])

    mcast_utils.log_debug('Finish processing snoop updates, ret=%d' % ret)
    return ret
Exemple #4
0
def remove_ebtables_rules(table, chain, rules):
    ret = True
    res = read_ebtable_rules(table, chain)

    ebtable_prefix = 'ebtables -t ' + table

    for rule in rules:
        if rule in res:
            cmd = (ebtable_prefix + ' -D ' + chain + rule).split()
            if (mcast_utils.run_command(cmd, res) != 0):
                ret = False
                mcast_utils.log_err("Failed to DELETE : %s " % (rule))
            else:
                mcast_utils.log_info("Succesfully DELETED : %s " % (rule))

    return ret
Exemple #5
0
def _parse_snoop_mrouter_ports(vlan_id, vlan_info, op, data, event_data):
    #scan through the leaf-list of mrouter ports.
    for interface in data:
        #Validate given interface is VLAN member
        if mcast_utils.is_intf_vlan_member(vlan_info, interface,
                                           vlan_id) is False:
            if op == "delete":
                #For delete case, when flow comes here there is a chance that port is
                # deleted from VLAN and NAS would have cleared multicast info.
                continue
            else:
                mcast_utils.log_err(
                    "interface %s is not VLAN %d member, skip processing" %
                    (str(interface), vlan_id))
                return False

    event_data.update({'vlan-id': vlan_id, 'mrouter-interface': data})
    return True
def _parse_snoop_routes(vlan_id, vlan_info, op, igmp_events, group_info,
                        pub_data):

    for key, val in group_info.items():
        if 'group' not in val:
            mcast_utils.log_err(
                "Route Event: VLAN %d Group not present, skip processing" %
                (vlan_id))
            continue
        if 'interface' not in val:
            mcast_utils.log_err(
                "Route Event: VLAN %d interface not present, skip processing" %
                (vlan_id))
            continue

        interface = val['interface']

        #Validate given interface is VLAN member
        if mcast_utils.is_intf_vlan_member(vlan_info, interface,
                                           vlan_id) is False:
            mcast_utils.log_err(
                "Route Event: interface %s is not VLAN %d member, skip processing"
                % (str(interface), vlan_id))
            if (op != "delete"):
                return False

            continue

        if mcast_utils._is_ip_addr(igmp_events, val['group']):
            group = val['group']
        elif igmp_events is True:
            group = ba.ba_to_ipv4str('ipv4', val['group'])
        else:
            group = ba.ba_to_ipv6str('ipv6', val['group'])

        pub_data.update({
            'vlan-id': vlan_id,
            ('group', key, 'interface'): interface,
            ('group', key, 'address'): group
        })

        if 'source-addr' in val:
            if mcast_utils._is_ip_addr(igmp_events, val['source-addr']):
                source = val['source-addr']
            elif igmp_events is True:
                source = ba.ba_to_ipv4str('ipv4', val['source-addr'])
            else:
                source = ba.ba_to_ipv6str('ipv6', val['source-addr'])

            pub_data.update({('group', key, 'source', '0', 'address'): source})
            mcast_utils.log_info(
                "Route event:VLAN %d Interface: %s Group %s Source %s" %
                (vlan_id, str(interface), group, source))
        else:
            mcast_utils.log_info(
                "Route Event: VLAN %d Interface %s Source not present, (*, %s) route "
                % (vlan_id, str(interface), group))
    return True
Exemple #7
0
def monitor_VLAN_interface_event():
    _vlan_handle = cps.event_connect()
    cps.event_register(_vlan_handle, _intf_vlan_key)
    mcast_utils.log_info('monitor_VLAN_interface_event started')

    while True:
        vlan_event = cps.event_wait(_vlan_handle)
        obj = cps_object.CPSObject(obj=vlan_event)
        if obj is None:
            mcast_utils.log_err(
                'VLAN_MONITOR: Object not present in the event')
            continue
        if obj.get_key() != _intf_vlan_key:
            mcast_utils.log_debug(
                'VLAN_MONITOR: Wrong VLAN interface event, ignore')
            continue

        try:
            vlan_name = obj.get_attr_data('if/interfaces/interface/name')
            # check if if_name is present
            if vlan_name is None:
                mcast_utils.log_err(
                    'VLAN_MONITOR: VLAN name not present in the event')
                continue

            if 'operation' in vlan_event:
                mcast_utils.log_info('VLAN_MONITOR: Received %s %s event' %
                                     (vlan_name, vlan_event['operation']))
                if (vlan_event['operation'] == 'create'):
                    ret = mcast_utils._update_file_system(
                        mcast_utils._get_path_per_vlan_configs(
                            vlan_name, "multicast_snooping"), 0)
                    if ret is True:
                        mcast_utils.log_info(
                            'VLAN_MONITOR: Disabled snooping on %s in kernel' %
                            (vlan_name))
                    else:
                        mcast_utils.log_err(
                            'VLAN_MONITOR: Failed to disable snooping on %s in kernel'
                            % (vlan_name))
                elif (vlan_event['operation'] == 'delete'):
                    #On VLAN deletion, not sure application sends the snoop disable, even if it sends it comes
                    #with VLAN id, so for getting ifname NAS interface may not have VLAN and will fail to get name.
                    #and per VLAN rule in kernel may not get deleted. So here on VLAN deletion the per VLAN IGMP/MLD
                    #rules are deleted.
                    #
                    if (snoop_remove_vlan_rules(True, vlan_name)) is False:
                        mcast_utils.log_debug(
                            'VLAN_MONITOR: Failed to remove IGMP ebtables rule in kernel for %s'
                            % (vlan_name))
                    if (snoop_remove_vlan_rules(False, vlan_name)) is False:
                        mcast_utils.log_debug(
                            'VLAN_MONITOR: Failed to remove MLD ebtables rule in kernel for %s'
                            % (vlan_name))
            else:
                mcast_utils.log_info(
                    'VLAN_MONITOR: Received event without operation' %
                    (vlan_name))

        except Exception as e:
            mcast_utils.log_err('VLAN_MONITOR: Exception: %s' % e)
Exemple #8
0
def snoop_remove_rule_chain(is_igmp):
    ret = True
    res = []
    mcast_utils.log_info('Remove %s chain' %
                         (IGMP_CHAIN_NAME if is_igmp else MLD_CHAIN_NAME))
    if is_igmp:
        rule_prefix = 'iptables -t raw '
        cmd = (rule_prefix + ' -C ' + igmp_preroute_rule).split()
        if (mcast_utils.run_command(cmd, res) == 0):
            cmd = (rule_prefix + ' -D ' + igmp_preroute_rule).split()
            if (mcast_utils.run_command(cmd, res) != 0): ret = ret and False

        ret = ret and snoop_delete_iptables_chain(is_igmp, 'raw',
                                                  IGMP_CHAIN_NAME)

        mcast_utils.log_info(
            'Remove %s chain ret = %d' %
            (IGMP_CHAIN_NAME if is_igmp else MLD_CHAIN_NAME, ret))

        #Delete EBTABLES nat POSTROUTING IGMP rules
        ret = remove_ebtables_rules(' nat ', ' POSTROUTING ',
                                    igmp_global_ebtable_rule)

        if ret is False:
            mcast_utils.log_err(
                'Failed to Delete EBTABLE IGMP rules from nat POSTROUTING chain'
            )
            return ret

        ret = snoop_bridge_nf_iptables_disable(is_igmp)
        if ret is False:
            mcast_utils.log_err('Failed to disable bridge_nf_call_iptables')
            return ret

    else:
        rule_prefix = 'ip6tables -t raw '
        cmd = (rule_prefix + ' -C ' + mld_preroute_rule).split()
        if (mcast_utils.run_command(cmd, res) == 0):
            cmd = (rule_prefix + ' -D ' + mld_preroute_rule).split()
            if (mcast_utils.run_command(cmd, res) != 0): ret = ret and False

        ret = ret and snoop_delete_iptables_chain(is_igmp, 'raw',
                                                  MLD_CHAIN_NAME)

        mcast_utils.log_info(
            'Remove %s chain ret = %d' %
            (IGMP_CHAIN_NAME if is_igmp else MLD_CHAIN_NAME, ret))

        #Delete EBTABLES nat POSTROUTING IGMP rules
        ret = remove_ebtables_rules(' nat ', ' POSTROUTING ',
                                    mld_global_ebtable_rule)

        if ret is False:
            mcast_utils.log_err(
                'Failed to Delete EBTABLE MLD rules from nat POSTROUTING chain'
            )
            return ret

        ret = snoop_bridge_nf_iptables_disable(is_igmp)
        if ret is False:
            mcast_utils.log_err('Failed to disable bridge_nf_call_ip6tables')
            return ret

    mcast_utils.log_info(
        'All %s global Ebtables/Iptables rules removed with ret = %d' %
        ('IGMP' if is_igmp else 'MLD', ret))
    return ret
Exemple #9
0
def snoop_add_rule_chain(is_igmp):

    ret = True
    res = []

    mcast_utils.log_debug('Create chain: %d' % (is_igmp))
    #EBTABLES:
    #For each snoop disabled VLAN's, received IGMP/MLD packets are marked
    #and dropped in iptables raw table IGMPSNOOP/MLDSNOOP chain.
    # Here:
    #1. Create IGMPSNOOP/MLDSNOOP chain in iptables raw table to check the
    #   IGMP/MLD packet types and drop all the iGMP/MLD packets other than query
    #   for enabled VLANs. For enabled VLAN's snoop application will decide what
    #   to do with the packet.
    #2. Create a Rule in iptables raw table PREROUTING chain to catch
    #   marked (snooping enabled VLAN's) IGMP/MLD packets and redirect to
    #   IGMPSNOOOP/MLDSNOOP chain
    if is_igmp:
        ret = snoop_create_iptables_chain(is_igmp, 'raw', IGMP_CHAIN_NAME)
        if ret is False:
            mcast_utils.log_err(
                'Failed to create/add iptables rules to %s chain' %
                (IGMP_CHAIN_NAME))
            return ret

        # Add PREROUTING rule
        rule_prefix = 'iptables -t raw '
        cmd = (rule_prefix + ' -C ' + igmp_preroute_rule).split()
        if (mcast_utils.run_command(cmd, res) != 0):
            cmd = (rule_prefix + ' -A ' + igmp_preroute_rule).split()
            if (mcast_utils.run_command(cmd, res) != 0): ret = ret and False

        if ret is False:
            mcast_utils.log_err(
                'Failed to add iptables rules to PREROUTING chain')
            return ret

        #Add EBTABLES nat POSTROUTING IGMP rules
        ret = add_ebtable_rules(' nat ', ' POSTROUTING ',
                                igmp_global_ebtable_rule)

        if ret is False:
            mcast_utils.log_err(
                'Failed to add IGMP EBTABLE rules to nat POSTROUTING chain')
            return ret

        ret = snoop_bridge_nf_iptables_enable(is_igmp)
        if ret is False:
            mcast_utils.log_err('Failed to enable bridge_nf_call_iptables')
            return ret

    else:
        ret = snoop_create_iptables_chain(is_igmp, 'raw', MLD_CHAIN_NAME)
        if ret is False:
            mcast_utils.log_err(
                'Failed to create/add ip6tables rules to %s chain' %
                (MLD_CHAIN_NAME))
            return ret

        # Add PREROUTING rule
        rule_prefix = 'ip6tables -t raw '
        cmd = (rule_prefix + ' -C ' + mld_preroute_rule).split()
        if (mcast_utils.run_command(cmd, res) != 0):
            cmd = (rule_prefix + ' -A ' + mld_preroute_rule).split()
            if (mcast_utils.run_command(cmd, res) != 0): ret = ret and False

        if ret is False:
            mcast_utils.log_err(
                'Failed to add ip6tables rules to PREROUTING chain')
            return ret

        mcast_utils.log_debug('%s chain created and rules added succesfully' %
                              (IGMP_CHAIN_NAME if is_igmp else MLD_CHAIN_NAME))

        #Add EBTABLES nat POSTROUTING MLD rules
        ret = add_ebtable_rules(' nat ', ' POSTROUTING ',
                                mld_global_ebtable_rule)

        if ret is False:
            mcast_utils.log_err(
                'Failed to add MLD EBTABLE rules to nat POSTROUTING chain')
            return ret

        ret = snoop_bridge_nf_iptables_enable(is_igmp)
        if ret is False:
            mcast_utils.log_err('Failed to enable bridge_nf_call_ip6tables')
            return ret

    mcast_utils.log_info(
        'All %s global Ebtables/Iptables created and rules added succesfully' %
        ('IGMP' if is_igmp else 'MLD'))

    return ret