Showing posts with label Cisco. Show all posts
Showing posts with label Cisco. Show all posts

Saturday, 16 March 2019

How to use 25G ports in 1/10G mode on Cisco NCS (540, 55A2, etc)

I've recently been test driving a Cisco NCS 55A2, which has 24 x 1/10 Gbps and 16 x 1/10/25 Gbps ports. However, I ran into a problem where the 1/10/25 Gbps ports would not rate adapt down to 10 Gbps. There is no "speed" configuration under the port and seemingly nothing useful under controllers relevant to 25G ports.

I eventually got the answer from Cisco engineering but since I couldn't find this documented anywhere on the Internet I thought it might be worth preserving it here for prosperity!

Theory


Unlike 1/10G operation where the device just detects what optic is inserted then presents the appropriate GigabitEthernet or TenGigabitEthernet interface, 1/10/25G ports need to be hard set into either 1/10G or 25G mode. Frustratingly, when it comes to 25 Gbps ports, the NCS platforms set this in groups of four ports, each of which is referred to as a"quad". In another confusing move, Cisco has decided to put the quad config in a completely different place to very similar things such as the config to break out 40/100G ports into 10/25G members.

Configuration


As we can see here, the 1/10/25G ports default to 25G mode, reflected in their TFx/x/x/x naming:

RP/0/RP0/CPU0:55A2(config)#do show interfaces description | begin 0/0/0/24
TF0/0/0/24 admin-down admin-down
TF0/0/0/25 admin-down admin-down
TF0/0/0/26 admin-down admin-down
TF0/0/0/27 admin-down admin-down
TF0/0/0/28 admin-down admin-down
TF0/0/0/29 admin-down admin-down
TF0/0/0/30 admin-down admin-down
TF0/0/0/31 admin-down admin-down
TF0/0/0/32 admin-down admin-down
TF0/0/0/33 admin-down admin-down
TF0/0/0/34 admin-down admin-down
TF0/0/0/35 admin-down admin-down
TF0/0/0/36 admin-down admin-down
TF0/0/0/37 admin-down admin-down
TF0/0/0/38 admin-down admin-down
TF0/0/0/39 admin-down admin-down
Mg0/RP0/CPU0/0 admin-down admin-down

Now, let's configure the first four 25G ports into 1/10G mode. The configuration lives under the "hw-module" branch, and quads are numbered from 0 (up to 3 on this platform). To set the first four ports into 1/10G mode:

RP/0/RP0/CPU0:55A2(config)#hw-module quad 0 location 0/0/CPU0 mode 10g
RP/0/RP0/CPU0:55A2(config)#commit

As we can see, ports 24-27 have transformed into 1/10G ports and now appear with the Tex/x/x/x naming convention:

RP/0/RP0/CPU0:55A2(config)#do show interfaces description | begin 0/0/0/24
Te0/0/0/24 admin-down admin-down
Te0/0/0/25 admin-down admin-down
Te0/0/0/26 admin-down admin-down
Te0/0/0/27 admin-down admin-down
TF0/0/0/28 admin-down admin-down
TF0/0/0/29 admin-down admin-down
TF0/0/0/30 admin-down admin-down
TF0/0/0/31 admin-down admin-down
TF0/0/0/32 admin-down admin-down
TF0/0/0/33 admin-down admin-down
TF0/0/0/34 admin-down admin-down
TF0/0/0/35 admin-down admin-down
TF0/0/0/36 admin-down admin-down
TF0/0/0/37 admin-down admin-down
TF0/0/0/38 admin-down admin-down
TF0/0/0/39 admin-down admin-down
Mg0/RP0/CPU0/0 admin-down admin-down

Let's set the rest to 10G mode, because 25G optics are expensive and I don't have any in the lab:

RP/0/RP0/CPU0:55A2(config)#hw-module quad 1 location 0/0/CPU0 mode 10g
RP/0/RP0/CPU0:55A2(config)#hw-module quad 2 location 0/0/CPU0 mode 10g
RP/0/RP0/CPU0:55A2(config)#hw-module quad 3 location 0/0/CPU0 mode 10g
RP/0/RP0/CPU0:55A2(config)#commit
RP/0/RP0/CPU0:55A2(config)#do show interfaces description | begin 0/0/0/24
Te0/0/0/24 admin-down admin-down
Te0/0/0/25 admin-down admin-down
Te0/0/0/26 admin-down admin-down
Te0/0/0/27 admin-down admin-down
Te0/0/0/28 admin-down admin-down
Te0/0/0/29 admin-down admin-down
Te0/0/0/30 admin-down admin-down
Te0/0/0/31 admin-down admin-down
Te0/0/0/32 admin-down admin-down
Te0/0/0/33 admin-down admin-down
Te0/0/0/34 admin-down admin-down
Te0/0/0/35 admin-down admin-down
Te0/0/0/36 admin-down admin-down
Te0/0/0/37 admin-down admin-down
Te0/0/0/38 admin-down admin-down
Te0/0/0/39 admin-down admin-down
Mg0/RP0/CPU0/0 admin-down admin-down

Easy (when you know how)!

Thursday, 27 April 2017

Hacky on-the-spot netflow

Sometimes it would be really useful to see what flows are active over a link, i.e. what is talking to what, but you don't have a netflow collector available (or the time to set one up). I was in this situation recently and discovered that it's possible to get most of the useful information out of netflow using just a Linux box and some scripting. Easy peasy.

1 - Configure Netflow on the Router / Firewall


There's not much to say about this, it varies from platform to platform, vendor to vendor, but you just need to set the device up to send Netflow version 5 to your "collector" box.

A couple of examples are here

Older IOS (12.x):


mls flow ip interface-full
ip flow-export version 5
ip flow-export destination x.x.x.x yyyy
interface Gix/x
  ip flow ingress
  mls netflow sampling

Juniper SRX:


set system ntp server pool.ntp.org
set interfaces fe-0/0/1 unit 0 family inet sampling input
set interfaces fe-0/0/1 unit 0 family inet sampling output
set forwarding-options sampling input rate 1024
set forwarding-options sampling family inet output flow-server x.x.x.x port yyyy
set forwarding-options sampling family inet output flow-server x.x.x.x version 5


2 - Capture the Netflow Packets


Use tcpdump / tshark / wireshark / whatever to capture the packets on the "collector" box. The only thing to be careful of is that you don't allow tcpdump to truncate / slice the packets, e.g.:

tcpdump -i eth0 -s 0 -w capfile.cap udp port yyyy and not icmp

The capture can be done on any box which your sampler can forward traffic to and from which you can retrieve the file back to a *nix box with tshark installed. If you have tshark installed on the capture box then you can also use it to dump the flows out.

3 - Dump the Flow Data with tshark


This can be done on the collector box if tshark is available or can be done elsewhere if not. Basically we ask tshark to dump out verbose packet contents then use standard *nix utilities to mangle the output:

tshark -r capfile.cap -nnV | grep -e '       \(...Addr:\|...Port:\|Protocol:\)' | tr '\n' ' ' | sed 's/       SrcAddr:/\n/g;' | awk '{print $1 "\t" $4 "\t" $7 "\t" $9 "\t" $10 $11}' | sed 's/Protocol:6/TCP/g; s/Protocol:17/UDP/g; s/Protocol:1/ICMP/g;'

This prints out the flows as reported by your router / firewall in tab separated columns as follows: Source IP, Destination IP, Source port, Destination port, IP Protocol

For example:

192.168.10.10  10.10.100.99    24010   53      UDP
192.168.8.14   10.10.100.4     0       771     ICMP
172.16.44.9    10.10.100.86    54832   443     TCP



Of course this can be tailored to match whatever fields interest you (for example you may want to include ingress and egress interfaces to show traffic direction or byte counts to get an idea of flow size) but this will cover the basics.

Saturday, 9 April 2016

Producing topology diagrams from OSPF database CLI output

I always imagined it should be possible to automatically produce a topology diagram from the information in the OSPF database of a router - in fact I've heard of products that allow you do do this by attaching a device into your network and joining the OSPF domain. For many cases that is too invasive or completely impractical - what would be really nice would be to be able to produce this directly from the CLI output of a "show" command.

After spending a bit of time looking around, I could not find a tool to do this so I went to work using Python and came up with a basic prototype in a couple of hours. The script doesn't actually do the plotting and layout but rather produces a DOT file leaves the heavy lifting to GraphViz. With a little extra work I have now produced a working script which takes the output of "show ip ospf database router" and produces a DOT file which can be used to plot a topology map showing each OSPF router complete with the links between (including metrics) and any transit multi-access networks.

CLI output from Cisco IOS and Cisco ASA is supported (the output seems to be essentially the same) and, obviously, it doesn't matter what vendors' kit is attached into the network, provided you run the "show ip ospf database router" on a supported platform.

The tool, not-so-snappily named "ospfcli2dot" is available from my github: https://github.com/theclam/ospfcli2dot

Example


Here's a simple example of a 4 router setup. R1, R2 and R3 all sit on a shared LAN, while R4 is attached point to point to R3 and R5:





The "show ip ospf database router" command can be run from any device in the network since all devices within an area share the same topology database. The output of this is quite verbose so will not be shown here. For the purposes of this example, I have just copied and pasted the output into a file called cli-output.txt.

Simply run the script against that file:

foeh@feeble ~/Projects/ospfcli2dot $ ./ospfcli2dot
ospfcli2dot - takes the output of "show ip ospf database router" and outputs a GraphViz DOT file corresponding to the network topology

v0.2 alpha, By Foeh Mannay, April 2016

Enter input filename: cli-output.txt
Enter output filename: example.dot
foeh@feeble ~/Projects/ospfcli2dot $ dot -Tgif -oexample.gif example.dot


This creates "example.gif", shown below:


As you can see, the metric is shown against each link and the script has automatically highlighted in red that one of the point to point links has different metrics in each direction.


Please give it a try and let me know how you get on!

Links


Download: https://github.com/theclam/ospfcli2dot

Sunday, 31 January 2016

Invalid Command Stopping Cisco 7600 Supervisor Redundancy Entering SSO / Hot Standby Mode

I recently ran into a problem when trying to apply a base build to a Cisco 7600 router with dual supervisors which didn't seem to be documented anywhere, so I thought I'd record the issue and the eventual fix here.

The gist of the problem was that the secondary supervisor would not go from cold standby to hot, so in other words if the active supervisor crashed, the chassis would have to reboot in order to use the standby supervisor. The system was showing the reason for this as software mismatch, even though the two cards had the same image installed:

BUILD#show redundancy states
       my state = 13 -ACTIVE
     peer state = 4  -STANDBY COLD
           Mode = Duplex
           Unit = Primary
        Unit ID = 5

Redundancy Mode (Operational) = rpr    Reason: Software mismatch
Redundancy Mode (Configured)  = sso
Redundancy State              = rpr
     Maintenance Mode = Disabled
 Communications = Up

   client count = 159
 client_notification_TMR = 30000 milliseconds
          keep_alive TMR = 9000 milliseconds
        keep_alive count = 1
    keep_alive threshold = 18
           RF debug mask = 0x0


I won't say exactly which image this was, but it was an SSO-capable relase of IOS 15 and the two supervisors were *definitely* running the same code (one was copied from the other). The tale of software incompatibility seemed unlikely.

BUILD#show log
[snip]
*Jan  6 17:21:33.339: %SYS-SP-STDBY-5-RESTART: System restarted --
Cisco IOS Software, c7600s72033_sp Software (c7600s72033_sp-ADVIPSERVICESK9-M), Version 15.x(x)x, RELEASE SOFTWARE (xx)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2012 by Cisco Systems, Inc.
Compiled Mon 00-Jan-00 00:00 by prod_rel_team
*Jan  6 17:22:50.255 GMT: Config Sync: Bulk-sync failure due to Servicing Incompatibility. Please check full list of mismatched commands via:
  show redundancy config-sync failures mcl
*Jan  6 17:22:50.255 GMT: Config Sync: Starting lines from MCL file:
-ipv6 mfib hardware-switching replication-mode ingress
*Jan  6 17:22:50.255 GMT: %ISSU-SP-3-INCOMPATIBLE_PEER_UID: Setting image (c7600s72033_sp-ADVIPSERVICESK9-M), version (15.x(x)xx) on peer uid (6) as incompatible
*Jan  6 17:22:50.995 GMT: %RF-SP-5-RF_RELOAD: Peer reload. Reason: ISSU Incompatibility
*Jan  6 17:22:50.995 GMT: %OIR-SP-3-PWRCYCLE: Card in module 6, is being power-cycled (RF request)
*Jan  6 17:22:51.999 GMT: %PFREDUN-SP-6-ACTIVE: Standby processor removed or reloaded, changing to Simplex mode
*Jan  6 17:22:53.195 GMT: %SNMP-5-MODULETRAP: Module 6 [Down] Trap
*Jan  6 17:24:19.791 GMT: %ISSU-SP-3-PEER_IMAGE_INCOMPATIBLE: Peer image (c7600s72033_sp-ADVIPSERVICESK9-M), version (15.x(x)xx) on peer uid (6) is incompatible
*Jan  6 17:24:19.791 GMT: %ISSU-SP-3-PEER_IMAGE_INCOMPATIBLE: Peer image (c7600s72033_sp-ADVIPSERVICESK9-M), version (15.x(x)xx) on peer uid (6) is incompatible
*Jan  6 17:25:53.149 GMT: %PFREDUN-SP-4-INCOMPATIBLE: Defaulting to RPR mode (Runtime incompatible)
*Jan  6 17:25:54.154 GMT: %PFREDUN-SP-6-ACTIVE: Standby initializing for RPR mode
*Jan  6 17:25:58.471 GMT: %SYS-SP-3-LOGGER_FLUSHED: System was paused for 00:00:00 to ensure console debugging output.
*Jan  6 17:25:58.763 GMT: %FABRIC-SP-5-CLEAR_BLOCK: Clear block option is off for the fabric in slot 6.
*Jan  6 17:25:58.859 GMT: %FABRIC-SP-5-FABRIC_MODULE_BACKUP: The Switch Fabric Module in slot 6 became standby
*Jan  6 17:26:00.299 GMT: %SNMP-5-MODULETRAP: Module 6 [Up] Trap
*Jan  6 17:26:00.279 GMT: %DIAG-SP-6-BYPASS: Module 6: Diagnostics is bypassed
*Jan  6 17:26:00.375 GMT: %OIR-SP-6-INSCARD: Card inserted in slot 6, interfaces are now online
*Jan  6 17:26:06.435 GMT: %RF-SP-5-RF_TERMINAL_STATE: Terminal state reached for (RPR)

OK, so clearly it doesn't like the "ipv6 mfib hardware-switching replication-mode ingress" command for some reason. Why it would work on one and not the other is a mystery but hey... I don't have big plans for IPv6 multicast so I don't care what replication mode it's in - let's just delete the offending command:

BUILD#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
BUILD(config)#no ipv6 mfib hardware-switching replication-mode ingress
no ipv6 mfib hardware-switching replication-mode ingress
         ^
% Invalid input detected at '^' marker.

So I can't negate the command, in fact there's no "mfib" stanza under "no ipv6":

BUILD(config)#no ipv6 ?
  access-list        Configure access lists
  [snip]
  local              Specify local options
  mld                Global mld commands
  [snip]
  spd                Selective Packet Discard (SPD)

In fact, even the original command seems to be invalid:

BUILD(config)#ipv6 mfib hardware-switching replication-mode ?
% Unrecognized command

And yet here it is in the config from which we booted:

BUILD#show start | inc ipv6 
ipv6 unicast-routing
ipv6 mfib hardware-switching replication-mode ingress
no mls flow ipv6

?!?!

I guess it's one of those legacy commands they bodge the CLI to take but you can't see in the help. But it won't take the command anyway :| Eventually I found an equivalent command that it *would* take:

BUILD(config)#no ipv6 multicast hardware-switching replication-mode ingress 
Warning: This command will change the replication mode for all address families.
 BUILD(config)#do show run | inc ipv6
ipv6 unicast-routing
no mls flow ipv6
BUILD(config)#



At last, the problem config is gone! We're almost there but not quite, the previous failures sit in the active supervisor even if the standby is reloaded so we have to kick it to re-evaluate:

BUILD#show redundancy config-sync failures mcl 
Mismatched Command List
-----------------------
-ipv6 mfib hardware-switching replication-mode ingress

BUILD#redundancy config-sync validate mismatched-commands  
*Jan  7 08:26:28.600 GMT: CONFIG SYNC: MCL validation succeeded
*Jan  7 08:26:28.600 GMT: %ISSU-SP-3-PEER_IMAGE_REM_FROM_INCOMP_LIST: Peer image (c7600s72033_sp-ADVIPSERVICESK9-M), version (15.x(x)xx) on peer uid (6) being removed from the incompatibility list
BUILD#show redundancy config-sync failures mcl 
Mismatched Command List
-----------------------

The list is Empty

BUILD#redundancy reload peer 
Reload peer [confirm]
Preparing to reload peer

BUILD#

*Jan  7 08:27:16.096 GMT:  RP sending reload request to Standby. User: admin on console, Reason: Admin reload CLI

BUILD#

Eventually...
 

*Jan  7 08:33:37.532 GMT: %HA_CONFIG_SYNC-6-BULK_CFGSYNC_SUCCEED: Bulk Sync succeeded*Jan  7 08:33:37.552 GMT: %RF-SP-5-RF_TERMINAL_STATE: Terminal state reached for (SSO)
*Jan  7 08:33:36.572 GMT: %PFREDUN-SP-STDBY-6-STANDBY: Ready for SSO mode
BUILD#show redundancy
Redundant System Information :
------------------------------
       Available system uptime = 15 hours, 20 minutes
Switchovers system experienced = 0
              Standby failures = 3
        Last switchover reason = none

                 Hardware Mode = Duplex
    Configured Redundancy Mode = sso
     Operating Redundancy Mode = sso
              Maintenance Mode = Disabled
                Communications = Up

Current Processor Information :
-------------------------------
               Active Location = slot 5
        Current Software state = ACTIVE
       Uptime in current state = 15 hours, 19 minutes
                 Image Version = Cisco IOS Software, c7600s72033_rp Software (c7600s72033_rp-ADVIPSERVICESK9-M), Version 15.x(x)xx, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2012 by Cisco Systems, Inc.
Compiled Wed 01-Aug-12 20:15 by prod_rel_team
                          BOOT = sup-bootdisk:/c7600s72033-advipservicesk9-mz.15x-x.xx.bin,1;
                   CONFIG_FILE =
                       BOOTLDR =
        Configuration register = 0x2102

Peer Processor Information :
----------------------------
              Standby Location = slot 6
        Current Software state = STANDBY HOT
       Uptime in current state = 3 minutes
                 Image Version = Cisco IOS Software, c7600s72033_rp Software (c7600s72033_rp-ADVIPSERVICESK9-M), Version 15.x(x)xx, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2012 by Cisco Systems, Inc.
Compiled Wed 01-Aug-12 20:15 by prod_rel_team
                          BOOT = sup-bootdisk:/c7600s72033-advipservicesk9-mz.15x-x.xx.bin,1;
                   CONFIG_FILE =
                       BOOTLDR =
        Configuration register = 0x2102
BUILD#

Win!

Saturday, 23 January 2016

Cisco Nexus Output Errors

A little while ago I was asked to investigate an IP based storage problem which had been traced back to a large amount of output errors on the port facing a particular compute node. The port was on a Cisco Nexus 5000 series device and I could see that, while output errors were clocking up at a massive rate, the switch was giving me nothing to go on as to what kind of errors they were. Every one of the usual suspects (collisions, etc) on the port showed nothing and yet the output errors were clocking up.

The ultimate answer turned out to be related to the fact that the Nexus 5k aims for low latency and as such performs cut-through switching. If you're not familiar with this term, please refer to this reasonably decent Cisco explanation, however at a high level there are two possible modes of transmission in switched networks:

1 - Store and Forward, where the entire frame is buffered into memory, the FCS is validated and then the frame is passed on. This mode can handle ports of differing speeds but obviously for large frames the serialisation delay becomes significant.
2 - Cut through, where just the header is checked for source / destination, plus any fields required for QoS / ACLs, then the rest of the frame is "cut through" onto the appropriate output port without buffering. This requires ports of an identical speed but offers lower latency.

One of the not-immediately-obvious side effects of cut through switching is that the FCS is only validated once the frame has been passed, by which point it is too late to take any corrective action. Essentially, the forwarding switch has already passed a broken fame on and, although it knows this, it can do nothing about it in retrospect and so it just says "oh, well" and increments its error counters on the ingress and egress ports.

If you are seeing output errors on a port with no other real explanation of how they got there, check other ports of the same speed for input errors. In my case it was due to a fibre fault - corrupted frames were entering one port, being cut through to another and causing errors to clock up on both.

Saturday, 11 July 2015

Testing the Impact of Local Packet Capture on the Cisco 6500 Series

For a while now, many of the larger Cisco devices (such as 6500 and 7600s) have supported local packet capture. I've always been hesitant to use these in a production environment, primarily due to concerns about the potential performance hit it could cause. Anyway, I decided to test out the potential impact in the lab to see whether it was sometimes / always / never safe to run local captures.

Test Setup

For my test setup I used a 6504-E switch with a modest SUP32-GE-3B supervisor and a 12.2 Advanced IP Services IOS - if it works on that, it should be safe anywhere. For traffic, I used a spare server running Ubuntu with a combination of Ostinato and Scapy.
The configuration was as follows:
Running at full tilt, Ostinato was happily producing 1 Gbps of traffic which went into my node on VLAN 100, out around the loop cable, back into the node and then out of the same interface on VLAN 101. Basically the port is running at 1 Gbps in each direction, so the worst possible case for mirroring a gig port.

Default Settings

The default settings for the capture are pretty conservative - a tiny 2 MB linear capture buffer with a rate limit of 10,000 frames per second. With this config, a 1 Gbps stream of 1500 byte packets fills the buffer in ~ 2.5s, triggering the capture to end. The impact of this is almost impossible to measure at all, with the capture being over so quickly you may not actually see any change in CPU on the 5 second roll-ups.
Lab-6503E#monitor capture start
*Jul 11 14:30:59.205: %SPAN-5-PKTCAP_START: Packet capture session 1 started
Lab-6503E#
*Jul 11 14:31:01.449: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended as the buffer is full, 21845 packets captured
Lab-6503E#show proc cpu hist
                                                              
                                                              
                         222223333322222               8888811
100                                                           
 90                                                           
 80                                                           
 70                                                           
 60                                                           
 50                                                           
 40                                                           
 30                                                           
 20                                                           
 10                                                    *****  
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5    
               CPU% per second (last 60 seconds)

Worst Case

OK, so the world didn't end. The next step was to see how bad it could be so I made the following changes:
  • Increased the rate limit to 100,000 fps (max)
  • Increased the packet buffer to 64 MB (max)
  • Enabled a circular buffer (why?!)
This time I set the capture to run for 60 seconds and checked the impact, which was much more severe:
Lab-6503E#monitor capture circular buffer size 65535 start for 60 sec
*Jul 11 14:45:02.953: %SPAN-5-PKTCAP_START: Packet capture session 1 started
*Jul 11 14:46:02.945: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 699040 packets captured
Lab-6503E#show proc cpu hist

    2222244444444444444455555444444444444444444444444444444444
    9999999999888889999966666999999999999999999998888899999999
100
 90
 80
 70
 60                     *****
 50      *****************************************************
 40      *****************************************************
 30 **********************************************************
 20 **********************************************************
 10 **********************************************************
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5

               CPU% per second (last 60 seconds)

The impact to the supervisor in this case was much more noticeable - up to 60% CPU utilisation. The scenario is pretty unrealistic (forget circular buffers!) but suffice to say I wouldn't want to do that on a production device.
Now we have a the best and the worst cases, let's look at some realistic use cases and explore some of the other capture parameters that might help us capture what we need without causing havoc on the network.

Narrowing Down the Capture

It's possible to define criteria to decide what gets captured - as the CLI points out, some of these criteria are processed in hardware while others are handled in software:
Lab-6503E(config-mon-capture)#filter ?
  access-group  Filter access-list (hardware based)
  ethertype     Matching ethertype (software based)
  length        Matching L2-packet length (software based)
  mac-address   Matching mac-address (software-based)
  vlan          Filter vlan (hardware based)
Our test traffic consists of nearly a gig of junk run alongside a small 1-per-second ping, which we will decide is "interesting" to us and we want to capture. This traffic profile makes it easy to test ACL, MAC address and length filters and their relative performances.

ACL Filter

As the CLI says, ACL filters are applied in hardware so the junk is discarded at source before it hits the CPU. In this example I set up an ACL as follows:
Lab-6503E(config)#ip access-list extended icmp-only
Lab-6503E(config-ext-nacl)#permit icmp any any
Lab-6503E(config-ext-nacl)#deny ip any any
... and applied it to my capture as follows:
Lab-6503E(config)#monitor session 1
Lab-6503E(config-mon-capture)#filter access-group icmp-only
Now, I re-ran the "worst case" test, with massively different results:
Lab-6503E#monitor capture circular buffer size 65535 start for 60 sec
*Jul 11 14:49:00.345: %SPAN-5-PKTCAP_START: Packet capture session 1 started
*Jul 11 14:50:00.337: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 60 packets captured
Lab-6503E#show proc cpu hist

         22222222223333355555          11111
100
 90
 80
 70
 60
 50
 40
 30
 20
 10                     *****
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5
               CPU% per second (last 60 seconds)
Two things to note here - because this is a hardware filter, applied in the ASICs:
  • Only 1 packet per second was punted to the CPU, resulting in essentially no hit at all
  • All 60 of the ping packets were received and nothing else
In summary, ACL filters are ideal when you know what you want to pull from a big stream as you only pay a CPU penalty for the "good stuff".

MAC Filter

In contrast, the MAC filter runs in software. It's also pretty limited, only matching on source MAC. I repeated the above test but instead of an ACL match, applied a MAC filter as follows:
Lab-6503E(config)#monitor session 1
Lab-6503E(config-mon-capture)#filter mac-address 0011.2233.4455
This took us more-or-less back to the worst case:
Lab-6503E#monitor capture circular buffer size 65535 start for 60 sec
*Jul 11 15:05:55.197: %SPAN-5-PKTCAP_START: Packet capture session 1 started
*Jul 11 15:06:55.189: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 5 packets captured
Lab-6503E#show proc cpu hist

      44444444443333344444333334444444444444444444444444333333
    4422222111119999900000999990000011111333331111111111888889
100
 90
 80
 70
 60
 50
 40   ********************************************************
 30   ********************************************************
 20   ********************************************************
 10   ********************************************************
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5
               CPU% per second (last 60 seconds)

Yuck. I wouldn't do that in production. This is basically because the software filters are applied after the packets have been punted to the CPU, so you pay a penalty for the garbage as well as the good stuff. You'll notice that it only captured 5 packets as well, more on this later but that's another side effect of software filters.

Length Filter

The frame length filter is another software-based mechanism, which means it's pretty terrible under load, too. Our junk traffic consists of large frames, our interesting traffic is small, so let's configure the capture to only catch the short frames:
Lab-6503E(config)#monitor session 1
Lab-6503E(config-mon-capture)#filter length 0 100 
Again, the output is pretty miserable:
Lab-6503E#monitor capture circular buffer size 65535 start for 60 sec
*Jul 11 15:15:12.145: %SPAN-5-PKTCAP_START: Packet capture session 1 started
*Jul 11 15:16:12.137: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 17 packets captured
Lab-6503E#show proc cpu hist

    1111444443333344444444443333333333333333333333333444443333
    4444000009999911111222229999999999999999999999999222229999
100
 90
 80
 70
 60
 50
 40     ******************************************************
 30     ******************************************************
 20     ******************************************************
 10 **********************************************************
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5
               CPU% per second (last 60 seconds)
Again, the CPU took a hammering and we only captured a few of the ping packets - 17 out of 60.

Quirks / Order of Operations

Now you may think that software filters might be OK if we just reduce the rate-limit configured on the capture:
Lab-6503E(config)#monitor session 1
Lab-6503E(config-mon-capture)#rate-limit 100
This *does* do what we want for the CPU load - here's an example with a MAC filter:
Lab-6503E#monitor capture circular buffer size 65535 start for 60 sec
*Jul 11 15:26:43.793: %SPAN-5-PKTCAP_START: Packet capture session 1 started
*Jul 11 15:27:43.785: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 0 packets captured
Lab-6503E#show proc cpu hist

                    11111          11111          6666633333
100
 90
 80
 70
 60
 50
 40
 30
 20
 10                                               *****
   0....5....1....1....2....2....3....3....4....4....5....5....
             0    5    0    5    0    5    0    5    0    5
               CPU% per second (last 60 seconds)
Great - nothing to see here. But also nothing to see in the capture buffer - 0 packets captured!
Just for fun let's try the same with a hardware ACL filter:
*Jul 11 15:25:26.921: %SPAN-5-PKTCAP_STOP: Packet capture session 1 ended after the specified time, 60 packets captured
Why is this? Well, it's the order of operations. Basically the flow for hardware ACL filters is:
So the filter throws out the junk before the rate limiter, meaning that the rate limiter only counts the good stuff. If the good stuff exceeds the rate limit then you'll lose some of it but the junk doesn't count.
Compare that to the flow for the software filters:
The software filters are applied after the rate limiter, so clearly when the rate limit is exceeded you throw out a mix of good and bad traffic, then pick out what's left of the good. If your traffic is overwhelmingly garbage, you may not get any of the good stuff at all!

Summary - Play it Safe

So in answer to the question "is it safe to run a local capture on a production 6500" - packet capture on even a relatively modest SUP32-3B supervisor is pretty safe provided you are cautious. If you want to do this in a busy production environment then my message to you is:
  • Use ACLs where at all possible
  • Set the rate limit to a sensible value (the default 1000 fps is fine for most cases)
  • Use linear buffers of a sensible size (do you really need 64MB of capture?)
  • Limit the frame count or capture duration at first (it may turn out there is a lot more "interesting" traffic than you thought!)
I'm convinced enough to do this in production but obviously I'm only testing one device, on one release of code, so don't blame me if you try it on something different and encounter a bug!

Sunday, 19 April 2015

Quick Build - Cisco IOS PPPoE Server with RADIUS Authentication

In this guide I'll show you how to quickly set up an IOS-based PPPoE access concentrator and a RADIUS server for it to authenticate against. As part of the setup I'll include both dynamic (pool based) IP subscribers and a fixed IP subscriber, which should cover most basic use cases.

The setup I describe will look like this (we will only build the RADIUS and the AC):



If you need a client to go with it, please check out my post titled Quick build - PPPoE Client on Cisco IOS

Stage 1 - The RADIUS Server


Firstly we'll configure the RADIUS server - the starting point for this is a completely clean install of Kali Linux. It makes no difference if this is running as a VM or on a physical box but you will probably run out of "disk space" if you try to do this from a live CD boot. This assumes that you either have configured an Internet connection or have a full Kali disc / image from which to install packages.

Task 1 - Configure the Network Interface


Edit /etc/networks/interfaces and add the following (adjust interface names as necessary):

auto eth1
iface eth1 inet static
    address 10.0.0.10
    netmask 255.255.255.0


Save the file, then run:

ifdown eth1
ifup eth1


Task 2 - Install FreeRADIUS


Assuming your Internet connection / Kali disc is accessible, just run:

apt-get update
apt-get install freeradius


Task 3 - Configure FreeRADIUS


The FreeRADIUS config files are pretty big and are mostly full of examples that aren't relevant to this setup, so we'll just set them aside and create new ones from scratch. Firstly we will replace the clients.conf file which tells FreeRADIUS which devices are allowed to authenticate against it.

Firstly, ditch the old one:
mv /etc/freeradius/clients.conf /etc/freeradius/ORIG-clients.conf

Next, edit /etc/freeradius/clients.conf and add:

client 10.0.0.100/32 {
    secret        = b0dges
    shortname    = PE1
    nastype        = cisco
}


Save the file and exit. Now do a similar thing with the users file (which is used to define how the users will be authenticated):

mv /etc/freeradius/users /etc/freeradius/ORIG-users

Edit /etc/freeradius/users and add:

DEFAULT         Auth-Type := CHAP, Cleartext-Password := "password1"
                    Framed-Protocol = PPP,
                    Framed-IP-Address = 255.255.255.254
foeh@fixed      Auth-Type := CHAP, Cleartext-Password := "password2"
                    Framed-Protocol = PPP,
                    Framed-IP-Address = 192.168.100.1


Save the file and exit. Note that the special "255.255.255.254" address above instructs the access concentrator to assign an IP locally from its pool.

Task 4 - Restart FreeRADIUS with the New Config


Simply run:

service freeradius restart


The service should restart without error. That's the difficult RADIUS config done, now onto the access concentrator!

Stage 2 - Configure the Access Concentrator


I'll go into a little more detail on this part as it's not quite as intuitive. The base device here is an IOS 12.3 router, Cisco's licensing model is complex and seems to vary wildly between platforms so I'll let you poke around in feature navigator to work out which feature set and release will work on your device... It seems to work fine on a 3845 running security services if that helps.

Task 1 - Configure Interfaces


We need a couple of interfaces configured here:
  • An interface towards RADIUS (obviously)
  • A loopback interface (used to address the "unnumbered" PPPoE tunnel interfaces)
  • A client interface (where the PPPoE users will attach)

interface FastEthernet1/0
 description To RADIUS
 ip address 10.0.0.100 255.255.255.0
 no shutdown
!
interface Loopback0

 description IP for Unnumbered Tunnel Interfaces
 ip address 1.1.1.1 255.255.255.255
!
interface FastEthernet0/1
 description To Clients
 no shutdown
!


We won't configure anything on the client interface for the moment but we will return to it momentarily...

Task 2 - Configure PPPoE


Firstly we need to configure a BBA group, which is just a way to associate a bunch of settings with a particular interface. We'll use the default "global" group and configure it to use virtual-template 1:

bba-group pppoe global
 virtual-template 1

Next, we need to define what Virtual-Template1 is. Virtual template interfaces are used to define a prototype on which to base the Virtual-Access (tunnel) interfaces which are automatically created when a PPPoE user connects. In this most simple of examples we just define where the interface's local IP address should be cloned from, where the PPPoE user's IP address should be allocated from and the authentication protocol we want to use:

interface Virtual-Template1
 ip unnumbered Loopback0
 peer default ip address pool localpool
 ppp authentication chap


The "peer default ip address" command above refers to a pool called "localpool", so we'd better create that:

ip local pool localpool 172.16.0.1 172.16.0.100

Now that we've defined all that good stuff, we need to apply the BBA group to the client interface:

interface FastEthernet0/1
 pppoe enable group global


Pretty simple so far and, in fact, that's most of the config done. All we need to do now is to...

Task 3 - Point the Router at the RADIUS


There are three relatively straightforward steps here, firstly we have to enable AAA new model on the device and then define the RADIUS server details (note, FreeRADIUS' ports differ from Cisco's defaults so we need to specify them):

aaa new-model
radius server kali
 address ipv4 10.0.0.10 auth-port 1812 acct-port 1813
 key b0dges


Then we have to tell the router to go to RADIUS when authenticating PPPoE users:

aaa authentication ppp default group radius
aaa authorization network default group radius


The second line is not necessary for dynamic IP users but instructs the router that it should allow RADIUS to tell it what the user's IP (and some other things) should be. If you leave out the last line then users with a RADIUS defined static IP will get one out of the pool like everyone else, so if RADIUS Framed-IP attributes are being ignored this is probably the cause.

Note: You may want to configure some local usernames for access to the CLI and add "aaa authentication login default local" or similar.

At this point, your PPPoE Access Concentrator with RADIUS authentication is ready for use!

If you're unsure how to set up a client, I've also written quick build posts for that:



Debugging


No build would be complete without a little bit of debugging. This is such a straightforward setup that, barring layer 3 issues, there's not a lot that can go wrong. Troubleshooting would pretty much be as follows:

  • Verify that you are getting PPPoE control traffic in from your client (debug pppoe packet, debug pppoe event). The sequence should be PADI, PADO, PADR, PADS. PADT indicates someone is pulling down the session, the debugs should show you who!
  • Check IP reachability to the RADIUS box using ping
  • Verify that FreeRADIUS is running (ps -aux | grep freeradius), start it if necessary (/etc/init.d/freeradius start)
  • If your client can't authenticate, check the password matches what's in FreeRADIUS (/etc/freeradius/users), not forgetting to restart FreeRADIUS if you make changes (/etc/init.d/freeradius restart)
  • If the passwords match but you are still getting authentication errors, verify that your secrets match between the router ("key" under "radius-server") and FreeRADIUS (/etc/freeradius/clients.conf), the NAS IP matches your router and that FreeRADIUS has been restarted since the last change (/etc/init.d/freeradius restart)
  •  Check your PPP is negotiating OK (debug ppp negotiation)
Some more tips that may be helpful can be found on my post about debugging Cisco PPPoE clients.

Quick build - PPPoE Client on Cisco IOS

In this quick-build guide I'll show you how to set up a very basic IOS-based PPPoE client. This example is from a Cisco 819 router, however the config is pretty much the same on most ISR type devices. As usual, the build will cover the most simple common use case (no VLAN tags, dynamic AC selection, negotiated IP).

Note, if you want a PPPoE access concentrator to go with your client, you may find the Quick Build: Cisco IOS PPPoE Server with RADIUS Authentication post useful.

The Setup



The PPPoE client is basically set up in two parts - the first being the physical interface which will connect towards the access concentrator, the second being a dialer interface that will become instantiated when the PPPoE session comes up. We'll build the physical interface first, as follows:

interface GigabitEthernet0
 description To AC
 pppoe enable pppoe-client dial-pool-number 1
 no shutdown
!

Pretty minimal... turn PPPoE on, and tell it which dialer pool to use. Note, in older versions of IOS the command was simply "pppoe-client dial-pool-number 1". Next, we have to configure the dialer interface, as follows:

interface Dialer1
 ip address negotiated
 encapsulation ppp
 dialer pool 1
 dialer-group 1
 ppp authentication chap callin
 ppp chap hostname user@domain
 ppp chap password 0 b0dges
!
dialer-list 1 protocol ip permit
ip route 0.0.0.0 0.0.0.0 Dialer1

This creates the dialer interface that we will use, tells it to use PPP and to pick up its IP address dynamically.

The "dialer pool" command places this dialer into the pool where the physical interface was set to look, while the "dialer-group" command specifies which dialer-list will be used to decide what traffic is interesting (i.e. will bring or keep the PPPoE session up).

The PPP commands force the authentication type to CHAP, specify that we will not make the AC authenticate to us (generally not supported) and set the CHAP hostname (think username) and password.

Finally, the dialer-list referred to in the earlier "dialer-group" command is defined to match any IP traffic at all, before a static route is used to force traffic out of the dialer interface.

That really is all that you need! In real life you will probably need to add NAT statements and you will definitely need at least one other interface, but that's the PPPoE part done.

Debugging


There's an entire post dedicated to this subject, but the short version is as follows:

  • Verify that you are getting PPPoE control traffic between your client and the server (debug pppoe packet, debug pppoe event). The sequence should be PADI, PADO, PADR, PADS. PADT indicates someone is pulling down the session, the debugs should show you who!
  • Check the static route has installed in your routing table as traffic will only trigger the PPP up if it hits the interface (show ip route)
  • Verify that there is at least one "up" IP interface on the box other than the dialer. If there's no source address usable then any test traffic will fail to encapsulate and you won't be able to bring PPP up. (show ip interfaces brief)
  • If your client can't authenticate, check the credentials (both hostname and password under the Dialer interface) and ensure that the authentication type is CHAP in "callin" mode.
  •  Check your PPP is negotiating OK (debug ppp negotiation)

Friday, 23 January 2015

Minimal SNMP View for Solarwinds Management of a Cisco Device

Some time ago, I was asked to provide a customer read-only SNMP access to a router so that they could monitor bandwidth utilisation. Unfortunately the device had some sensitive configuration which needed to be protected, so giving access to the full MIB was not an option. With that in mind, I set up an SNMP view which permitted access to the ifMIB and nothing else, thinking that would be sufficient to monitor interface usage.

The customer tested and soon came back to advise me that, although he could successfully run an SNMP walk, his Solarwinds NMS could not discover the device and therefore he couldn't get the stats he needed.

It turns out that Solarwinds needs a particular set of OIDs to be visible before it will allow a device to be discovered and brought under management. There are a few articles on the knowledge base about which OIDs it uses for various purposes, e.g:

http://knowledgebase.solarwinds.com/kb/questions/1196/

However, there doesn't seem to be one directly addressing the question of which OIDs are required just to bring a device under management.

Eventually I think I gave up and sniffed a discovery off the wire and looked at which OIDs it used -  I don't exactly remember any more. Anyway, here is a list that seems to do the trick. The following CLI should configure a minimal set of OIDs on a Cisco device:

snmp-server view STATS iso excluded
snmp-server view STATS mib-2 excluded
snmp-server view STATS cisco excluded
snmp-server view STATS system.1.0 included
snmp-server view STATS system.2.0 included
snmp-server view STATS system.4.0 included
snmp-server view STATS system.5.0 included
snmp-server view STATS system.6.0 included
snmp-server view STATS ifIndex included
snmp-server view STATS ifDescr included
snmp-server view STATS ifSpeed included
snmp-server view STATS ifOperStatus included
snmp-server view STATS ipAddrEntry.2 included
snmp-server view STATS lsystem.8 included
snmp-server view STATS lsystem.58 included
snmp-server view STATS chassis.6 included
snmp-server view STATS ifName included
snmp-server view STATS ifHCInOctets included
snmp-server view STATS ifHCInUcastPkts included
snmp-server view STATS ifHCInMulticastPkts included
snmp-server view STATS ifHCInBroadcastPkts included
snmp-server view STATS ifHCOutOctets included
snmp-server view STATS ifHCOutUcastPkts included
snmp-server view STATS ifHCOutMulticastPkts included
snmp-server view STATS ifHCOutBroadcastPkts included
snmp-server view STATS ifHighSpeed included
snmp-server view STATS ifAlias included
snmp-server view STATS ciscoMemoryPoolEntry.5 included
snmp-server view STATS ciscoMemoryPoolEntry.6 included
snmp-server view STATS cpmCPUTotalTable.1.5 included
snmp-server view STATS cpmCPUTotalTable.1.8 included

Once the view is defined, you just need to apply it to the particular community string for SNMPv2:

snmp-server community mycomm view STATS RO

Or the user for SNMPv3:

snmp-server group Monitoring v3 priv read STATS write STATS

This config allowed SolarWinds to discover the device and bring it under management. It also allowed basic port stats to be collected and general up/down alarms to be raised.

Of course, you can add more OIDs into the "included" list as needed for your particular use case, however these should be enough for SolarWinds to discover the device.

Monday, 12 January 2015

Bending the MPLS Security Model - part 3 (Layer 2 Injection)

Attack 1 - layer 2 injection

Back in the days when I did solution validation and regression testing for a living, I normally had to set up full solutions in the lab, built to specific designs. I would then often need test egress QoS policies, filters and so on. To be sure that ingress QoS and filters did not invalidate the results, I had a few options:

1. Temporarily remove the ingress policies, making sure they were re-applied correctly afterwards and that nobody else tested in the mean time

2. Build a duplicate service but instead of terminating the far end on a real device, emulate everything from IGP up on a tester

3. Cheat

Option 1 is pretty risky as "temporary" easily turns into "permanent" if you're not very careful. Option 2 is a lot of work and runs the risk of compromising the design in order to inter-operate with the tester.

Given that the drawbacks of the other available options, I usually fell back on option 3. What I would do is set up the service as per design, then attach the tester somewhere in the MPLS core - basically any port that would label switch. The tester didn't need to peer any protocols at all, saving huge amounts of setup and troubleshooting time, as the packets would be hand crafted in true "dirty hack" style. All I had to do was look at the label bindings on the egress PE to work out what service label to use and on the first hop router to see what transport label needed to be used.

I'll make this example a little simpler by getting a router to do the ARP, work out the transport label and encapsulate the packets. Rest assured that it's perfectly possible to do this by hand if you don't have a real PE. We'll take a simple pseudowire service as an example. We have the following setup:



We want to make our traffic from device X come out of the PE towards LAN B, as if it had been sent through from LAN A. Two things are needed for this:

  1. The transport label that will get traffic forwarded to router B
  2. The service label that PE B expects to receive for the pseudowire
Now in my lab example, I could just log onto each of the devices and get these. The transport label to get to PE B can be found in the output of the neighbouring router's "show mpls ldp bindings" or similar, in our example we will just let the "evil" PE learn it via LDP.  The service label could be found in the bindings list for PE A or PE B, may be sniffed from live traffic if you have access to somewhere in the switching path, or can be guessed using the information in the previous post.
Anyway, we can use the evil PE to do most of the donkey work for us as far as encapsulation goes. With a fairly simple config, the PE can be made to inject into whatever service we like. Because this is a static config, the evil PE doesn't tell any other devices we are doing this.

Here's the config from the evil PE (Cisco IOS):

mpls label range 100 1048575 static 16 99
!
interface GigabitEthernet1/1
 no ip address
 xconnect 10.255.255.2 100 encapsulation mpls manual
  mpls label 99 19
  mpls control-word
!

The blue section simply reserves part of the label range for static allocation. The actual numbers aren't important but in order to build the bogus EoMPLS service we need to statically assign an incoming label (even though it will never be used). By default, IOS doesn't reserve any of the label space for static allocation and, until you do, you can't assign a manual label. In this example we designate that labels 100 - 1048575 are to be used for dynamic allocation (i.e. given out by LDP, BGP) and labels 16 - 99 are reserved for static allocation, though the actual numbers aren't important.

The red section looks very similar to a normal EoMPLS service build, except for the use of the keyword "manual" and the MPLS tweaks inside. The manual keyword does exactly what you would expect, i.e. it tells the router that this VC will not be signalled using LDP but rather the parameters are going to be manually (statically) configured. 

Once in the xconnect context we define what labels the service will use in each direction - inbound first (we don't care what this is) and then outbound (this has to match the label expected by the EoMPLS service into which we are trying to inject traffic). Remember, you may have to guess the outbound label if you don't have access to either of the serving PEs.

Finally, depending on the vendor and / or configuration of the serving PEs you may need to adjust the control-word setting. Cisco and recent Junipers default to enabled, Alcatel-Lucent and older Junipers default to disabled. 

Now, assuming the label is correct, any frames attacker "X" sends into the Evil PE will come out of the MPLS core and hit user B as if they had been sent by user A. This is unidirectional so the potential for "connecting" to anything is not really there, however there is a massive amount of harm that can be done at this point. Possible attacks range from a simple flood to spanning tree & LACP attacks, even creating IP conflicts or interfering with the operation of routing protocols.

Worked Example


Here's an example showing how an attacker can use the setup above to wreak havoc by throwing in some random PVST packets. The customer setup is as below, with a Cisco switch attached to each of the provider edge routers and a layer 2 service running between.


Note, the switches are running PVST over the link as per default. If a switch sees a BPDU marked as being from the "wrong" VLAN it will decide the port is "broken" (Cisco's terminology, not mine) and block it.

As an attacker we can use this to our advantage by sending frames for 2 different VLAN IDs towards one of the switches. That way, whatever the native VLAN ID of the receiving port is set to, at least one of the VLAN IDs will be incorrect and force the switch to block.

Here's a scruffy scapy loop to do that:

>>> import time
>>> outint='eth0'
>>> bridgemac='\x00\x00\x00\x00\x00\x01'

>>> while True:
...   sendp(Dot3(src='00:00:00:00:00:01', dst='01:80:c2:00:00:00')/LLC(dsap=170,ssap=170,ctrl=3)/Raw(load='\x00\x00\x0c\x01\x0b\x00\x00\x00\x00\x00\x80\x00'+bridgemac+'\x00\x00\x00\x00'+'\x80\x00'+bridgemac+'\x80\x01'+'\x00\x00\x14\x00\x02\x00\x0f\x00\x00'+'\x00\x00\x00\x02'+'\x00\x02'),iface=outint)
...   time.sleep(10)
...   sendp(Dot3(src='00:00:00:00:00:01', dst='01:80:c2:00:00:00')/LLC(dsap=170,ssap=170,ctrl=3)/Raw(load='\x00\x00\x0c\x01\x0b\x00\x00\x00\x00\x00\x80\x00'+bridgemac+'\x00\x00\x00\x00'+'\x80\x00'+bridgemac+'\x80\x01'+'\x00\x00\x14\x00\x02\x00\x0f\x00\x00'+'\x00\x00\x00\x02'+'\x00\x03'),iface=outint)
... 
.
Sent 1 packets.
^C

As long as the loop continues, the port will always remain down. A nice DoS that would be pretty hard to figure out, even if the console messages are quite clear (below from a single BDPU):

SW2#
*Mar  1 02:04:21.755: %SPANTREE-2-RECV_PVID_ERR: Received BPDU with inconsistent peer vlan id 3 on FastEthernet0/1 VLAN1.
*Mar  1 02:04:21.755: %SPANTREE-2-BLOCK_PVID_LOCAL: Blocking FastEthernet0/1 on VLAN1. Inconsistent local vlan.
SW2#PVST+: restarted the forward delay timer for FastEthernet0/1

SW2#
*Mar  1 02:04:36.831: %SPANTREE-2-UNBLOCK_CONSIST_PORT: Unblocking FastEthernet0/1 on VLAN1. Port consistency restored.
SW2# PVST+:Inconsistency timer expired. inconsistency 0
                 cleared for FastEthernet0/1

One bad PVST+ BPDU will generally cause the port to block for anywhere between 10 and 50s. It's extremely efficient :)

References