Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions ansible/roles/configure/files/helpers/conv_acl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/python
Copy link
Contributor

@qiluo-msft qiluo-msft Mar 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is never used? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was used to convert ACL rules list from the xml format to the json file for the swssconfig
If we ever decide to update the list of the rules (from the different xml) we will need this tool


import calendar
import os
import sys
import socket
import struct
import json
import copy
import ipaddr as ipaddress
from collections import defaultdict

from lxml import etree as ET
from lxml.etree import QName

def dump_json(filename, data):
with open(filename, 'w') as outfile:
json.dump(data, outfile, indent=4, sort_keys=True, separators=(',', ':'))

# Return: res, value, n (num of consumed elements)
def is_port(props, idx):
if idx >= len(props):
return False, "", 0
if props[idx] == "eq":
return True, props[idx+1], 2
if props[idx] == "gt":
return True, props[idx+1]+"-65535", 2
if props[idx] == "lt":
return True, "1-"+props[idx+1], 2
if props[idx] == "range":
return True, props[idx+1]+"-"+props[idx+2], 3
return False, "", 0

def is_subnet(props, idx):
if idx >= len(props):
return False, "", 0
if props[idx] == "any":
return True, ""
try:
socket.inet_aton(props[idx].split("/")[0])
return True, props[idx]
except socket.error:
False, ""

def generate_rule_json(table_name, rule_idx, rule):
rule_props_list = rule.text.split()
rule_props = {}
rule_data = {}
rule_data["ACL_RULE_TABLE:"+table_name+":Rule_"+str(rule_idx)] = rule_props
rule_data["OP"] = "SET"
rule_props["priority"] = "10"
if rule_props_list[0] == "permit":
rule_props["PACKET_ACTION"] = "FORWARD"
elif rule_props_list[0] == "deny":
rule_props["PACKET_ACTION"] = "DROP"
else:
print "Unknown rule action %s in table %s, rule %d!" % (rule_props_list[0], table_name, rule_idx)

if rule_props_list[1] == "ip":
rule_props["IP_TYPE"] = "IPV4ANY"
elif rule_props_list[1] == "tcp":
rule_props["IP_PROTOCOL"] = "6" # TCP protocol
elif rule_props_list[1] == "icmp":
rule_props["IP_PROTOCOL"] = "1" # ICMP protocol
elif rule_props_list[1] == "udp":
rule_props["IP_PROTOCOL"] = "17" # UDP protocol
else:
try:
int(rule_props_list[1])
except:
print "Unknown rule protocol %s in table %s, rule %d!" % (rule_props_list[1], table_name, rule_idx)
return {}
else:
rule_props["IP_PROTOCOL"] = rule_props_list[1]


res, val = is_subnet(rule_props_list, 2)
if not res:
print "Src subnet error\n"
return {}
elif val:
rule_props["SRC_IP"] = val

i = 3
res, val, n = is_port(rule_props_list, i)
if res:
if val.find("-") < 0:
rule_props["L4_SRC_PORT"] = val
else:
rule_props["L4_SRC_PORT_RANGE"] = val

i+=n


res, val = is_subnet(rule_props_list, i)
if not res:
print "Dst subnet error"
return {}
elif val:
rule_props["DST_IP"] = val
i+=1

res, val, n = is_port(rule_props_list, i)
if res:
if val.find("-") < 0:
rule_props["L4_DST_PORT"] = val
else:
rule_props["L4_DST_PORT_RANGE"] = val
i+=n

if i < len(rule_props_list):
if rule_props_list[i] == "rst":
rule_props["TCP_FLAGS"] = "0xFF/0x04"
if rule_props_list[i] == "ack":
rule_props["TCP_FLAGS"] = "0xFF/0x10"
if rule_props_list[i] == "syn":
rule_props["TCP_FLAGS"] = "0xFF/0x02"

return rule_data


def generate_table_json(policies):
table_name = ""
#print policy.attrib
table_name = "ACL_Table"

table_props = {}
table_props["policy_desc"] = table_name
table_props["type"] = "L3"
table_props["ports"] = ",".join("Ethernet%d" % x for x in range(0, 128, 4))

table_data = [{}]
table_data[0]["ACL_TABLE:"+table_name] = table_props
table_data[0]["OP"] = "SET"
dump_json("table_"+table_name+".json", table_data)

rule_idx = 0
rule_data = []
for policy in policies:
for rule in policy.findall("Rule"):
rule_props = generate_rule_json(table_name, rule_idx, rule)
if rule_props:
rule_data.append(rule_props)
rule_idx+=1

dump_json("rules_for_"+table_name+".json", rule_data)

def xml_to_json(filename):
root = ET.parse(filename).getroot()

for acl in root.findall("AccessControlList"):
for aclgr in acl.findall("AclGroup"):
generate_table_json(aclgr.findall("Policy"))

return


def main():
xml_to_json(sys.argv[1])

def debug_main():
print_parse_xml('switch1')

from ansible.module_utils.basic import *

if __name__ == "__main__":
main()
22 changes: 22 additions & 0 deletions ansible/roles/configure/files/helpers/swssconfig_args_update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
Copy link
Contributor

@qiluo-msft qiluo-msft Mar 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script is lacking comment. Could you also give some samples?
More general question: is it ever possible to test the DUT without changing the content of the docker container? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added comment and usage example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change is not for the test. It adds permanent configuration for the testbed. To let it survive the reboot I have to modify start.sh


# This script updates the SWSSCONFIG_ARGS variable inside the given shell script with the list of files according to given file mask
#
# Usage example:
# to update line
# SWSSCONFIG_ARGS="some_existing.json "
# inside the /usr/bin/start.sh with the all json files located in /etc/swss/config.d/acl/
# execute:
# swssconfig_args_update.sh /usr/bin/start.sh /etc/swss/config.d/acl/*.json'
#
# example of the resulting line:
# SWSSCONFIG_ARGS="some_existing.json acl1.json acl2.json "
#

OLD_LINE=`cat ${1} | grep SWSSCONFIG_ARGS=`
STR_ADD=`ls ${2} | sed 's#.*/##' | tr '\n' ' '`

if echo ${OLD_LINE} | grep -v "${STR_ADD}"; then
NEW_LINE="${OLD_LINE%\"*}${STR_ADD}\""
awk -v old_line="${OLD_LINE}" -v new_line="${NEW_LINE}" '{ if ($0 == old_line) print new_line ; else print $0}' ${1} >/tmp/new_conf && mv /tmp/new_conf ${1}
fi
51 changes: 51 additions & 0 deletions ansible/roles/configure/tasks/acltb_permanent_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#-----------------------------------------
# Apply ACL configuration
#-----------------------------------------
- set_fact:
acltb_configs:
- "{{ 'acltb_persistent_acl_table' }}"
- "{{ 'acltb_persistent_acl_rules' }}"

# Gather minigraph facts
- name: Gathering minigraph facts about the device
minigraph_facts: host={{ inventory_hostname }}
become: no
connection: local

- name: Print neighbors in minigraph
debug: msg="{{ minigraph_neighbors }}"

- name: Read port reverse alias mapping
set_fact:
alias_reverse_map: "{{ lookup('file', 'roles/sonicv2/files/ssw/{{ sonic_hwsku }}/alias_reverse_map.json') | from_json }}"

- block:
- name: Generate and copy ACL permanent configuration to DUT/swss
become: true
template: src={{ item }}.j2
dest=/etc/swss/config.d/{{ item }}.json
mode=0644
with_items:
- "{{ acltb_configs }}"

- name: Copy start.sh modification script to the DUT/swss
copy: src=roles/configure/files/helpers/swssconfig_args_update.sh
dest=/tmp/swssconfig_args_update.sh
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swssconfig_args_update.sh [](start = 20, length = 25)

I noticed you copy the script (swssconfig_args_update.sh) to remote and run it. You may try 'script' module to simplify the steps.

mode=0755

- name: Modify start.sh to apply ACL config on start (table)
shell: /tmp/swssconfig_args_update.sh /usr/bin/start.sh /etc/swss/config.d/{{ item }}.json
become: yes
with_items:
- "{{ acltb_configs }}"

- name: Apply ACL configuration
shell: swssconfig /etc/swss/config.d/{{ item }}.json
with_items:
- "{{ acltb_configs }}"
tags: acltb_configure

vars:
ansible_shell_type: docker
ansible_python_interpreter: docker exec -i swss python

31 changes: 31 additions & 0 deletions ansible/roles/configure/tasks/config_decap.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
- fail: msg="information about testbed missing."
when: (lo_ip is not defined) or
(dscp_mode is not defined)

Copy link
Contributor

@sihuihan88 sihuihan88 Apr 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me ask a silly question: after the interface is configured following decap rule, is there any way to reset it back to a normal interface? If so how could we do it?

- fail: msg="Invalid testbed_type value '{{dscp_mode}}'"
when: dscp_mode not in [ 'pipe','uniform']

- block:
- name: Copy JSON configs into docker filesystem
template: src=decap_conf.j2 dest=/etc/swss/config.d/decap_config.json

- name: Copy start.sh modification script to the DUT/swss
copy: src=roles/configure/files/helpers/swssconfig_args_update.sh
dest=/tmp/swssconfig_args_update.sh
mode=0755

- name: Modify start.sh to apply decap config on start (rule)
command: /tmp/swssconfig_args_update.sh /usr/bin/start.sh /etc/swss/config.d/decap_config.json
become: yes

- name: Load decap JSON config.
shell: swssconfig /etc/swss/config.d/decap_config.json
register: valid_config_upload
failed_when: valid_config_upload.rc != 0
tags: decap

vars:
ansible_shell_type: docker
ansible_python_interpreter: docker exec -i swss python


18 changes: 18 additions & 0 deletions ansible/roles/configure/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#-----------------------------------------
# Apply ACL permanent configuration
#-----------------------------------------

- name: ACL configuration
include: acltb_permanent_config.yml
tags: acl
#-----------------------------------------
# Apply Everflow permanent configuration
#-----------------------------------------

#-----------------------------------------
# Apply IPinIP permanent configuration
#-----------------------------------------
- name: Decap configuration
include: config_decap.yml
tags: decap

Loading