SRX Performance Testing

For a project, I had to gather data in order to measure the SRX performance under different traffic loads. This was done for a SRX chassis system in cluster mode. The following commands were utilized in order to capture metrics when the system was subjected to traffic load:

show system uptime 
show system statistics
 
show chassis routing-engine 
show chassis fpc 
show chassis cluster status 
show chassis cluster information 
show chassis cluster interfaces 
 
show security monitoring 
show security monitoring performance spu 
show security flow statistics

show interfaces reth0 statistics
show security monitoring fpc node all <fpc-slot>

Github with scripts to execute the above commands and save it in a file.

Ansible – Cisco Config Implementation

The goal of this article is to explain configuration implementation on Cisco IOS after the config has been generated as shown in Ansible Config Generator III:

config-implementation.yml

---
- hosts: switch
  gather_facts: true
  connection: local
 
  tasks:
  - name: OBTAIN LOGIN CREDENTIALS
    include_vars: secrets.yml
 
  - name: DEFINE PROVIDER
    set_fact:
      provider:
        host: "{{ inventory_hostname }}"
        username: "{{ creds['username'] }}"
        password: "{{ creds['password'] }}"
        auth_pass: "{{ creds['auth_pass'] }}"
 
  - name: CONFIGURE INTERFACE
    ios_config:
      provider: "{{ provider }}"
      authorize: yes
      lines:
        - "{{ lookup('file', './config-output/{{ inventory_hostname }}.conf') }}"

The “hosts” file contains the switch names:

[switch]
switch-1
switch-2
switch-3
switch-4

secrets.yml

---
creds:
  username: cisco
  password: ciscopassword
  auth_pass: ciscoauthpassword

“./config-output/” directory contains the following files:

switch-1.conf
switch-2.conf
switch-3.conf
switch-4.conf

The inventory file (hosts) contains the switches in which the configuration from corresponding file name will be added. “switch-1.conf” file contents will be utilized to configure “switch-1” so on and so forth.

~/ansible_play/config-output$ cat switch-1.conf 
            
int Gi1/1                   
switchport access vlan 195
            
int Gi1/10                   
switchport access vlan 188
 
~/ansible_play/config-output$ cat switch-2.conf 
            
int Gi1/2                   
switchport access vlan 295
            
int Gi1/20                   
switchport access vlan 288
 
~/ansible_play/config-output$ cat switch-3.conf 
            
int Gi1/3                   
switchport access vlan 395
            
int Gi1/30                   
switchport access vlan 388
 
~/ansible_play/config-output$ cat switch-4.conf 
            
int Gi1/4                   
switchport access vlan 495
            
int Gi1/40                   
switchport access vlan 488

Ansible – Config Generator III

For Part I & Part II of this series.

The goal of this playbook is to be able to generate unique configuration for each switch. In this case, we are configuring a port to work as an access-port for a specific vlan. The port and vlan variable is different for each switch.

config-gen.yml

---
- hosts: 127.0.0.1
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./templates/accessvlan.j2
      dest: ./config-output/{{ item.switch }}.conf
    with_items: "{{ file_vlan }}"

file.yml

---
file_vlan:
- { switch: switch-1, port: Gi1/8,  vlan: 395 }
- { switch: switch-1, port: Gi1/23, vlan: 388 }
- { switch: switch-2, port: Gi1/8,  vlan: 395 }
- { switch: switch-2, port: Gi1/23, vlan: 388 }
- { switch: switch-3, port: Gi1/9,  vlan: 395 }
- { switch: switch-3, port: Gi1/24, vlan: 388 }
- { switch: switch-4, port: Gi1/9,  vlan: 395 }
- { switch: switch-4, port: Gi1/24, vlan: 388 }

accessvlan.j2

{% for grouper, host in file_vlan|groupby('switch') %}
{% if item.switch == grouper %}
{% for item in host %}            
int {{ item.port }}                   
switchport access vlan {{ item.vlan }}
{% endfor %}
{% endif %}
{% endfor %}

When the “config-gen.yml” playbook is executed:

ansible-playbook config-gen.yml

we get the following output files:

~/ansible_play/config-output$ cat switch-1.conf 
            
int Gi1/1                   
switchport access vlan 195
            
int Gi1/10                   
switchport access vlan 188
 
~/ansible_play/config-output$ cat switch-2.conf 
            
int Gi1/2                   
switchport access vlan 295
            
int Gi1/20                   
switchport access vlan 288
 
~/ansible_play/config-output$ cat switch-3.conf 
            
int Gi1/3                   
switchport access vlan 395
            
int Gi1/30                   
switchport access vlan 388
 
~/ansible_play/config-output$ cat switch-4.conf 
            
int Gi1/4                   
switchport access vlan 495
            
int Gi1/40                   
switchport access vlan 488

Ansible – Config Generator – II

For the first part of this series, check this – 1st part of this series.

---
- hosts: local
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./SVI.j2
      dest: ./{{ item.vlan }}.conf
    with_items: "{{ file_vlan }}"

 

This is the file.yml that is being referenced in the “include_vars”

---
file_vlan:
- { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
- { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

Compared to the 1st part of this series, we are moving the contents of the “with_items” to a separate YAML file and calling it based on the variable name “file_vlan” that is part of the file content.

MSS & MTU

Always, MTU > MSS

Without any TCP or IP Options in the packet:

MSS + 40 Bytes = MTU

The 40B is used to represent 20B of IP header and 20B of TCP header. The addition in number of bytes can be more than 40B depending on options in the header.

Standard Ethernet Frame: 1500B. Ethernet Header and CRC: 18B. MTU refers to Ethernet Payload without the header and CRC.

Ethernet Fram Size = Header + Standard Ethernet Fram (1500B) + CRC

Reference Link.

F5 – SSL Cert Expiration

K14318 – Identifying expired certs and certs about to expire in 30 days.

K15288 – Email reminder for cert expiration.

A few one-liners from bash to identify the cert expiration date:

Identifying the expiration date from the certificate name:

~ # tmsh list sys file ssl-cert domain.crt | grep expiration
    expiration-date 1505951999
    expiration-string "Sep 20 23:59:59 2017 GMT"

 

Identifying the Client SSL profile for a certificate:

~ # tmsh list ltm profile client-ssl one-line | grep domain.crt | awk '{print $3,$4}'
    client-ssl CLIENTSSL-domain.com

 

Identifying the Virtual Server from Client SSL profile:

~ # tmsh list ltm virtual one-line | grep CLIENTSSL-domain.com | awk '{print $2,$3}'
    virtual VS-10.10.10.10-Public

 

Identifying the expiration date for cert associated with VS:

~ # echo | openssl s_client -connect 10.10.10.10:443 2> /dev/null | openssl x509 -noout -dates
notBefore=Nov 21 00:00:00 2016 GMT
notAfter=Nov 22 23:59:59 2017 GMT

 

Ansible – Config Generator – I

Before proceeding, make sure to install “netaddr” as this is required for “ipaddr()” used in the Jinja2 configuration template.

pip install netaddr

aggr.yml is the playbook that will be utilized for generating L3 SVI configuration:

---
- hosts: local
  connection: local
  gather_facts: no

tasks:
- name: GENERATE CONFIG
  template:
  src: ./SVI.j2
  dest: ./{{ item.vlan }}.conf
  with_items:
  - { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
  - { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

This is the SVI.j2 Jinja2 template that is being utilized to generate the final configuration:

###### A-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('2') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 120
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

###### B-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('3') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 110
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

In my setup, the play-book (aggr.yml), source template SVI.j2 file and the destination file exist in the same folder.

Reference Github.

Ansible – Encrypting Password

Basic Ansible automation playbook provides a method for accessing Cisco IOS devices and executing “show commands”. The “secrets.yml” file contains the username and password in plain-text. ansible-vault can be utilized to encrypt the “secrets.yml” file.

Encrypt a file using ansible-vault:

ansible-vault encrypt secrets.yml

View the contents of an encrypted file:

ansible-vault view secrets.yml

Decrypt a file using ansible-vault:

ansible-vault decrypt secrets.yml

Ansible – Basic Playbook

The goal of this post is to provide you with a simple way to utilize Ansible 2.x and obtain data from Cisco IOS devices by running “show” commands. Github Reference.

Ansible Installation:

Before starting, make sure you have ansible installed.

Create a working directory:

mkdir ansible_play
cd ansible_play

Create the following 4 files within the “ansible_play” directory:

ansible.cfg
hosts
secrets.yml
show_code.yml

Among the 4 files provided in this example, the “hosts” and “secrets.yml” file would have to be altered to suit your requirements. The other 2 files, “ansible.cfg” and “show_code.yml” can be used as-is.

The contents of the above files will be like this:

$ cat ansible.cfg

[defaults]
hostfile = ./hosts
host_key_checking=False
timeout = 5

For now, use the contents as provided above for the “ansible.cfg” file.

$ cat hosts

[ios]
switch1

The hosts file will have the switches/routers that you would like to use for running the ansible-playbook. In my case, I am using “switch1”. The 1st line “[ios]” is the name of the hosts that will be referenced in the ansible-playbook.

$ cat secrets.yml

---
creds:
  username: cisco
  password: ciscopassword
  auth_pass: ciscoauth

This file contains the login information required to access the devices in the hosts file.

$ cat show_code.yml

---
- hosts: ios
  gather_facts: no
  connection: local
 
  tasks:
  - name: OBTAIN LOGIN CREDENTIALS
    include_vars: secrets.yml
 
  - name: DEFINE PROVIDER
    set_fact:
      provider:
        host: "{{ inventory_hostname }}"
        username: "{{ creds['username'] }}"
        password: "{{ creds['password'] }}"
        auth_pass: "{{ creds['auth_pass'] }}"
 
  - name: SHOW VERSION
    ios_command:
      provider: "{{ provider }}"
      commands:
        - show version | i Version
    register: write
 
  - debug: var=write.stdout_lines

Executing the ansible playbook:

$ ansible-playbook show_code.yml

PLAY [ios] *********************************************************************

TASK [OBTAIN LOGIN CREDENTIALS] ************************************************
ok: [switch1]

TASK [DEFINE PROVIDER] *********************************************************
ok: [switch1]

TASK [SHOW VERSION] ************************************************************
ok: [switch1]

TASK [debug] *******************************************************************
ok: [switch1] => {
    "write.stdout_lines": [
        [
            "Cisco IOS Software, Catalyst 4500 L3 Switch  Software (cat4500e-ENTSERVICESK9-M), Version 15.2(2)E3, RELEASE SOFTWARE (fc3)"
        ]
    ]
}

PLAY RECAP *********************************************************************
switch1               : ok=4    changed=0    unreachable=0    failed=0

 

 

F5 Virtual Server – Order of Precedence

The VS order of predence differs with code version and the tm.continuematching db variable. This tm.continuematching db variable is set to false by default and hence, a lower predence VS does not handle the traffic if there exists an higher predence VS in a disabled state. If the traffic has to be handled by lower precedence VS when the higher precedence VS is disabled, we would have to set this db variable as true:

11.x Code Version:

(tmos)# modify /sys db tm.continuematching value true
(tmos)# save /sys config

9.x – 10.x Code Version:

bigpipe db TM.ContinueMatching true
bigpipe save all

The order of predence for VS processing for different code version is provided below.

Order of Precedence for code version: 9.2 – 11.2.x

<address>:<port>
 <address>:*
 <network>:<port>
 <network>:*
 *:<port>
 *:*

Order of Precedence for code version: 11.3 and later

Order Destination Source Service port
1 <host address> <host address> <port>
2 <host address> <host address> *
3 <host address> <network address> <port>
4 <host address> <network address> *
5 <host address> * <port>
6 <host address> * *
7 <network address> <host address> <port>
8 <network address> <host address> *
9 <network address> <network address> <port>
10 <network address> <network address> *
11 <network address> * <port>
12 <network address> * *
13 * <host address> <port>
14 * <host address> *
15 * <network address> <port>
16 * <network address> *
17 * * <port>
18 * * *