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
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
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
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)
def snoop_get_cb(methods, params): mcast_utils.log_debug('Snoop get not supported') return False
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
def read_ebtable_rules(table, chain): cmd = ('ebtables -t ' + table + ' -L ' + chain).split() res = [] mcast_utils.run_command(cmd, res) mcast_utils.log_debug("ebtable dump: %s" % (res)) return res