Arista DirectFlow Integration with iRulesLX
Problem this snippet solves:
What the heck is DirectFlow?
Arista offers a functionality in certain platforms that allows for an administrative software-defined flow definition that supersedes the RIB/FIB. This allows for an administrator to override the switch's default forwarding behavior dynamically. For all intents, consider it a static route that can be defined via API.
More information, straight from the horse's mouth: EOS Section 48.1: Introduction - Arista
What is this DirectFlow Assist that I've heard about?
Some third-party equipment can't do fancy things such as make an API call. They require the customer to install and manage special software on the Arista device(s) that allows them to send information in a simpler way (syslog, for example) and have that special middleware on the Arista device receive, parse and ultimately create the DirectFlow entry. Stateless, best effort, a shot in the dark from the hip. Fortunately, the BIG-IP wears big boy shoes and can make these API calls natively. Who wants to break an integration on the next Arista EOS upgrade because third-party software wasn't upgraded as well? Not you!
So how does the BIG-IP come into play?
Imagine, midnight in the data center and the backups kick off. Links that have seen low-to-moderate flow all day start seeing amped-up, jumbo-framed backup packets in the tens or hundreds of gigabits. This starts putting stress on intelligent network services, such as ADC, firewall, IPS, etc., which makes little sense for many organizations. What if the BIG-IP could see that traffic and proclaim with authority, "Hey, I know what this is! Friendly but huge packets, you don't need to pass through these gates eternally... Arista, handle this!" Faster than a shooting star, the BIG-IP sends an API call defining the desired flow path to the Arista and the Arista bypasses the firewall for the remaining traffic of that flow! Firewall once, switch many (FOSM, which rhymes with awesome.) So fast that when tested, the BIG-IP saw the TCP SYN and the flow was cached on the Arista before the SYN ACK made it back.
But what about that evil attacker at 263.53.13.11 (that's coveted Class F space in IPv5) spewing digital hate over the wire? The BIG-IP can detect and instruct the Arista to drop any traffic coming from that IP address. These are just a few examples, I'm sure you can come up with more!
How to use this snippet:
So how does this work?
By the power of iRulesLX, the Stag's Leap of network programmability. We have an iRule such as this:
when FLOW_INIT { set ilx_handle [ILX::init "arista_directflow_create" "arista_directflow_create"] if { [IP::protocol] == 6 } { # TCP Handler set flow_id [expr { int(100000000000 * rand()) }] log local0. "TCP($flow_id):VLAN_[LINK::vlan_id]:SRCADDR_[IP::remote_addr]:SRCPORT_[TCP::remote_port]:DSTADDR_[IP::local_addr]:DSTPORT_[TCP::local_port]" set ip_protocol "tcp" set source_addr [IP::remote_addr] set dest_addr [IP::local_addr] set dest_port [TCP::local_port] if { [catch { set res [ILX::call $ilx_handle "createDirectflowEntry" "$flow_id" "[LINK::vlan_id]" "$ip_protocol" "$source_addr" "$dest_addr" "$dest_port" ]} result]} { log local0.error "ILX Failure: $result" return } } elseif { [IP::protocol] == 17 } { # UDP Handler set flow_id [expr { int(100000000000 * rand()) }] log local0. "UDP($flow_ID):VLAN_[LINK::vlan_id]:SRCADDR_[IP::remote_addr]:SRCPORT_[UDP::remote_port]:DSTADDR_[IP::local_addr]:DSTPORT_[UDP::local_port]" set ip_protocol "udp" set source_addr [IP::remote_addr] set dest_addr [IP::local_addr] set dest_port [UDP::local_port] if { [catch { set res [ILX::call $ilx_handle "createDirectflowEntry" "$flow_id" "[LINK::vlan_id]" "$ip_protocol" "$source_addr" "$dest_addr" "$dest_port" ]} result]} { log local0.error "ILX Failure: $result" return } } else { # Other protocols log local0. "Ignoring unmatched IP protocol [IP::protocol] from [IP::remote_addr] to [IP::local_addr]" } }
That triggers our API call to the Arista:
/* * create a directflow entry on Arista EOS * */ var rpc = require('node-json-rpc2'); var exports = module.exports = {}; /** * create directflow entry * * @param {String} command * @return {Object} data */ exports.createDirectflowEntry = function(flow_id, source_vlan, ip_protocol, source_address, destination_address, destination_port, callback) { var options = { port: 80, host: '192.168.1.10', path: '/command-api', strict: true, user: "f5test", pass: "mypassword" }; var client = new rpc.Client(options); client.call( { "jsonrpc":"2.0", "method":"runCmds", "params":{ "format":"json", "timestamps":false, "cmds":[ "configure terminal", "directflow", "flow " + flow_id, "no persistent", "timeout idle 15", "match ip protocol " + ip_protocol, "match source ip " + source_address, "match destination ip " + destination_address, "match destination port " + destination_port, "action set vlan 4093", "action set destination mac a1:2b:3c:4d:5e:6f", "action output interface et5", "flow " + flow_id + "-inverse", "no persistent", "timeout idle 15", "match ip protocol " + ip_protocol, "match source ip " + destination_address, "match destination ip " + source_address, "match source port " + destination_port, "action set vlan " + source_vlan, "action set destination mac aa:bb:cc:11:22:33", "action output interface et6", "end" ], "version":1 }, "id":"EapiExplorer-1"}, function(err, res) { callback(err) } ); };
The full setup instructions are included in the GitHub repository, along with EOS-specific versions of the iRule. This could be improved, but is a great starting point for the integration. Unfortunately, you need to put your hands on physical Arista hardware, as the vEOS VMs don't support the syntax even. Good luck and have fun!
Tested this on version:
No Version Found