Beispiel #1
0
def test_self_mac_not_learnt(ptfadapter, rand_selected_dut, pkt_type,
                             toggle_all_simulator_ports_to_rand_selected_tor_m,
                             tbinfo):
    """
    Verify self mac will not be learnt.
    """
    # Clear existing FDB entry from DUT
    rand_selected_dut.command('sonic-clear fdb all')
    # Sleep some time to ensure clear is done
    time.sleep(5)
    if pkt_type == "cleanup":
        return

    mg_facts = rand_selected_dut.get_extended_minigraph_facts(tbinfo)
    port_index = random.choice(list(
        mg_facts['minigraph_ptf_indices'].values()))
    self_mac = rand_selected_dut.facts['router_mac']
    dummy_mac = "00:22:33:44:33:22"
    if pkt_type == "ethernet":
        send_eth(ptfadapter, port_index, self_mac, dummy_mac, 0)
    elif pkt_type == "arp_request":
        send_arp_request(ptfadapter, port_index, self_mac, dummy_mac, 0)
    elif pkt_type == "arp_reply":
        send_arp_reply(ptfadapter, port_index, self_mac, dummy_mac, 0)
    # Sleep some time to ensure FDB is populate
    time.sleep(5)
    # Verify that self mac is not learnt
    fdb_facts = rand_selected_dut.fdb_facts()['ansible_facts']
    pytest_assert(self_mac not in fdb_facts,
                  "Self-mac {} is not supposed to be learnt".format(self_mac))
Beispiel #2
0
def setup_fdb(ptfadapter, vlan_table, router_mac, pkt_type, dummy_mac_count):
    """
    :param ptfadapter: PTF adapter object
    :param vlan_table: VLAN table map: VLAN subnet -> list of VLAN members
    :return: FDB table map : VLAN member -> MAC addresses set
    """

    fdb = {}

    assert pkt_type in PKT_TYPES

    for vlan in vlan_table:
        for member in vlan_table[vlan]:
            if 'port_index' not in member or 'tagging_mode' not in member:
                continue
            # member['port_index'] is a list,
            # front panel port only has one member, and portchannel might have 0, 1 and multiple member ports,
            # portchannel might have no member ports or all member ports are down, so skip empty list
            if not member['port_index']:
                continue
            port_index = member['port_index'][0]
            vlan_id = vlan if member['tagging_mode'] == 'tagged' else 0
            mac = ptfadapter.dataplane.get_mac(0, port_index)
            # send a packet to switch to populate layer 2 table with MAC of PTF interface
            send_eth(ptfadapter, port_index, mac, router_mac, vlan_id)

            # put in learned MAC
            fdb[port_index] = {mac}

            # Send packets to switch to populate the layer 2 table with dummy MACs for each port
            # Totally 10 dummy MACs for each port, send 1 packet for each dummy MAC
            dummy_macs = [
                '{}:{:02x}:{:02x}'.format(DUMMY_MAC_PREFIX, port_index, i)
                for i in range(dummy_mac_count)
            ]

            for dummy_mac in dummy_macs:
                if pkt_type == "ethernet":
                    send_eth(ptfadapter, port_index, dummy_mac, router_mac,
                             vlan_id)
                elif pkt_type == "arp_request":
                    send_arp_request(ptfadapter, port_index, dummy_mac,
                                     router_mac, vlan_id)
                elif pkt_type == "arp_reply":
                    send_arp_reply(ptfadapter, port_index, dummy_mac,
                                   router_mac, vlan_id)
                else:
                    pytest.fail("Unknown option '{}'".format(pkt_type))

            # put in set learned dummy MACs
            fdb[port_index].update(dummy_macs)

    time.sleep(FDB_POPULATE_SLEEP_TIMEOUT)
    # Flush dataplane
    ptfadapter.dataplane.flush()

    return fdb
Beispiel #3
0
  def _handle_arp_PacketIn(self,event,packet,dpid,inport):
    """ Learns the inport the switch receive packets from the given IP address
    
    Keyword Arguments:
    event -- the event that triggered this function call
    packet -- IP packet
    dpid -- the switch id
    inport -- 
    
    """
    a = packet.next  # 'a' seems to be an IP packet (or actually it's an ARP packet)
    
    log.debug("%i %i ARP %s %s => %s", dpid, inport,{arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
       'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst))
    
    if a.prototype == arp.PROTO_TYPE_IP:
      if a.hwtype == arp.HW_TYPE_ETHERNET:
        if a.protosrc != 0:
          
          if multicast.is_mcast_address(a.protodst,self):
            log.debug("skipping normal ARP Request code because ARP request is for multicast address %s" %(str(a.protodst)))
            
            if a.protodst in multicast.installed_mtrees:
              print "already setup mcast tree for s%s, inport=%s,dest=%s, just resending the ARP reply and skipping mcast setup." %(dpid,inport,a.protodst)
              utils.send_arp_reply(packet, a, dpid, inport, self.arpTable[dpid][a.protodst].mac, self.arpTable[dpid][a.protodst].port)
            else:
              #getting the outport requires that we have run a "pingall" to setup the flow tables for the non-multicast addreses
              outport = utils.find_nonvlan_flow_outport(self.flowTables,dpid, a.protosrc, multicast.h1)
              self.arpTable[dpid][a.protodst] = Entry(outport,multicast.mcast_mac_addr)
              utils.send_arp_reply(packet, a, dpid, inport, self.arpTable[dpid][a.protodst].mac, self.arpTable[dpid][a.protodst].port)
            
            return

          # Learn or update port/MAC info for the SOURCE address 
          if a.protosrc in self.arpTable[dpid]:
            if self.arpTable[dpid][a.protosrc] != (inport, packet.src):
              log.info("%i %i RE-learned %s", dpid,inport,str(a.protosrc))
          else:
            log.debug("%i %i learned %s", dpid,inport,str(a.protosrc))
            
          self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src)

          if a.opcode == arp.REQUEST:
            # Maybe we can answer

            if a.protodst in self.arpTable[dpid]:
              # We have an answer...

              if not self.arpTable[dpid][a.protodst].isExpired():
                # .. and it's relatively current, so we'll reply ourselves
                
                r = arp()
                r.hwtype = a.hwtype
                r.prototype = a.prototype
                r.hwlen = a.hwlen
                r.protolen = a.protolen
                r.opcode = arp.REPLY
                r.hwdst = a.hwsrc
                r.protodst = a.protosrc #IP address
                r.protosrc = a.protodst #IP address
                r.hwsrc = self.arpTable[dpid][a.protodst].mac
                e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc)
                e.set_payload(r)   # r is the ARP REPLY
                log.debug("%i %i answering ARP for %s" % (dpid, inport,
                 str(r.protosrc)))
                msg = of.ofp_packet_out()
                msg.data = e.pack()
                msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
                msg.in_port = inport
                event.connection.send(msg)
                return

    # Didn't know how to answer or otherwise handle this ARP request, so just flood it
    log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport,
     {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
     'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst)))

    msg = of.ofp_packet_out(in_port = inport, action = of.ofp_action_output(port = of.OFPP_FLOOD))
    if event.ofp.buffer_id is of.NO_BUFFER:
      # Try sending the (probably incomplete) raw data
      msg.data = event.data
    else:
      msg.buffer_id = event.ofp.buffer_id
    event.connection.send(msg.pack())