Skip to content

Commit

Permalink
Merge branch 'sonic-net:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
651477787 authored Jun 30, 2023
2 parents fa063ba + 73d8d63 commit fc63cac
Show file tree
Hide file tree
Showing 80 changed files with 4,092 additions and 395 deletions.
11 changes: 0 additions & 11 deletions .azure-pipelines/docker-sonic-vs/Dockerfile

This file was deleted.

61 changes: 52 additions & 9 deletions acl_loader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class AclLoader(object):
"ETHERTYPE_LLDP": 0x88CC,
"ETHERTYPE_VLAN": 0x8100,
"ETHERTYPE_ROCE": 0x8915,
"ETHERTYPE_ARP": 0x0806,
"ETHERTYPE_ARP": 0x0806,
"ETHERTYPE_IPV4": 0x0800,
"ETHERTYPE_IPV6": 0x86DD,
"ETHERTYPE_MPLS": 0x8847
Expand Down Expand Up @@ -156,9 +156,9 @@ def __init__(self):

namespaces = multi_asic.get_all_namespaces()
for front_asic_namespaces in namespaces['front_ns']:
self.per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
self.per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(namespace=front_asic_namespaces)
self.per_npu_configdb[front_asic_namespaces].connect()
self.per_npu_statedb[front_asic_namespaces] = SonicV2Connector(use_unix_socket_path=True, namespace=front_asic_namespaces)
self.per_npu_statedb[front_asic_namespaces] = SonicV2Connector(namespace=front_asic_namespaces)
self.per_npu_statedb[front_asic_namespaces].connect(self.per_npu_statedb[front_asic_namespaces].STATE_DB)

self.read_tables_info()
Expand Down Expand Up @@ -261,7 +261,7 @@ def read_acl_object_status_info(self, cfg_db_table_name, state_db_table_name):
else:
state_db_info = self.statedb.get_all(self.statedb.STATE_DB, "{}|{}".format(state_db_table_name, state_db_key))
status[key]['status'] = state_db_info.get("status", "N/A") if state_db_info else "N/A"

return status

def get_sessions_db_info(self):
Expand Down Expand Up @@ -346,6 +346,14 @@ def is_table_l3v6(self, tname):
"""
return self.tables_db_info[tname]["type"].upper() == "L3V6"

def is_table_l3v4v6(self, tname):
"""
Check if ACL table type is L3V4V6
:param tname: ACL table name
:return: True if table type is L3V4V6 else False
"""
return self.tables_db_info[tname]["type"].upper() == "L3V4V6"

def is_table_l3(self, tname):
"""
Check if ACL table type is L3
Expand Down Expand Up @@ -509,6 +517,17 @@ def convert_ip(self, table_name, rule_idx, rule):
# "IP_ICMP" we need to pick the correct protocol number for the IP version
if rule.ip.config.protocol == "IP_ICMP" and self.is_table_ipv6(table_name):
rule_props["IP_PROTOCOL"] = self.ip_protocol_map["IP_ICMPV6"]
elif rule.ip.config.protocol == "IP_ICMP" and self.is_table_l3v4v6(table_name):
# For L3V4V6 tables, both ICMP and ICMPv6 are supported,
# so find the IP_PROTOCOL using the ether_type.
try:
ether_type = rule.l2.config.ethertype
except Exception as e:
ether_type = None
if rule.l2.config.ethertype == "ETHERTYPE_IPV6":
rule_props["IP_PROTOCOL"] = self.ip_protocol_map["IP_ICMPV6"]
else:
rule_props["IP_PROTOCOL"] = self.ip_protocol_map[rule.ip.config.protocol]
else:
rule_props["IP_PROTOCOL"] = self.ip_protocol_map[rule.ip.config.protocol]
else:
Expand Down Expand Up @@ -544,9 +563,20 @@ def convert_ip(self, table_name, rule_idx, rule):
def convert_icmp(self, table_name, rule_idx, rule):
rule_props = {}

is_table_v6 = self.is_table_ipv6(table_name)
type_key = "ICMPV6_TYPE" if is_table_v6 else "ICMP_TYPE"
code_key = "ICMPV6_CODE" if is_table_v6 else "ICMP_CODE"
is_rule_v6 = False
if self.is_table_ipv6(table_name):
is_rule_v6 = True
elif self.is_table_l3v4v6(table_name):
# get the IP version type using Ether-Type.
try:
ether_type = rule.l2.config.ethertype
if ether_type == "ETHERTYPE_IPV6":
is_rule_v6 = True
except Exception as e:
pass

type_key = "ICMPV6_TYPE" if is_rule_v6 else "ICMP_TYPE"
code_key = "ICMPV6_CODE" if is_rule_v6 else "ICMP_CODE"

if rule.icmp.config.type != "" and rule.icmp.config.type != "null":
icmp_type = rule.icmp.config.type
Expand Down Expand Up @@ -651,7 +681,18 @@ def convert_rule_to_db_schema(self, table_name, rule):
rule_props["PRIORITY"] = str(self.max_priority - rule_idx)

# setup default ip type match to dataplane acl (could be overriden by rule later)
if self.is_table_l3v6(table_name):
if self.is_table_l3v4v6(table_name):
# ETHERTYPE must be passed and it should be one of IPv4 or IPv6
try:
ether_type = rule.l2.config.ethertype
except Exception as e:
raise AclLoaderException("l2:ethertype must be provided for rule #{} in table:{} of type L3V4V6".format(rule_idx, table_name))
if ether_type not in ["ETHERTYPE_IPV4", "ETHERTYPE_IPV6"]:
# Ether type must be v4 or v6 to match IP fields, L4 (TCP/UDP) fields or ICMP fields
if rule.ip or rule.transport:
raise AclLoaderException("ethertype={} is neither ETHERTYPE_IPV4 nor ETHERTYPE_IPV6 for IP rule #{} in table:{} type L3V4V6".format(rule.l2.config.ethertype, rule_idx, table_name))
rule_props["ETHER_TYPE"] = str(self.ethertype_map[ether_type])
elif self.is_table_l3v6(table_name):
rule_props["IP_TYPE"] = "IPV6ANY" # ETHERTYPE is not supported for DATAACLV6
elif self.is_table_l3(table_name):
rule_props["ETHER_TYPE"] = str(self.ethertype_map["ETHERTYPE_IPV4"])
Expand Down Expand Up @@ -682,6 +723,8 @@ def deny_rule(self, table_name):
rule_props["IP_TYPE"] = "IPV6ANY" # ETHERTYPE is not supported for DATAACLV6
elif self.is_table_l3(table_name):
rule_props["ETHER_TYPE"] = str(self.ethertype_map["ETHERTYPE_IPV4"])
elif self.is_table_l3v4v6(table_name):
rule_props["IP_TYPE"] = "IP" # Drop both v4 and v6 packets
else:
return {} # Don't add default deny rule if table is not [L3, L3V6]
return rule_data
Expand Down Expand Up @@ -835,7 +878,7 @@ def show_table(self, table_name):
for key, val in self.get_tables_db_info().items():
if table_name and key != table_name:
continue

stage = val.get("stage", Stage.INGRESS).lower()
# Get ACL table status from STATE_DB
if key in self.acl_table_status:
Expand Down
96 changes: 96 additions & 0 deletions config/dns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

import click
from swsscommon.swsscommon import ConfigDBConnector
from .validated_config_db_connector import ValidatedConfigDBConnector
import ipaddress


ADHOC_VALIDATION = True
NAMESERVERS_MAX_NUM = 3


def to_ip_address(address):
"""Check if the given IP address is valid"""
try:
ip = ipaddress.ip_address(address)

if ADHOC_VALIDATION:
if ip.is_reserved or ip.is_multicast or ip.is_loopback:
return

invalid_ips = [
ipaddress.IPv4Address('0.0.0.0'),
ipaddress.IPv4Address('255.255.255.255'),
ipaddress.IPv6Address("0::0"),
ipaddress.IPv6Address("0::1")
]
if ip in invalid_ips:
return

return ip
except Exception:
return


def get_nameservers(db):
nameservers = db.get_table('DNS_NAMESERVER')
return [ipaddress.ip_address(ip) for ip in nameservers]


# 'dns' group ('config dns ...')
@click.group()
@click.pass_context
def dns(ctx):
"""Static DNS configuration"""
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
config_db.connect()
ctx.obj = {'db': config_db}


# dns nameserver config
@dns.group('nameserver')
@click.pass_context
def nameserver(ctx):
"""Static DNS nameservers configuration"""
pass


# dns nameserver add
@nameserver.command('add')
@click.argument('ip_address_str', metavar='<ip_address>', required=True)
@click.pass_context
def add_dns_nameserver(ctx, ip_address_str):
"""Add static DNS nameserver entry"""
ip_address = to_ip_address(ip_address_str)
if not ip_address:
ctx.fail(f"{ip_address_str} invalid nameserver ip address")

db = ctx.obj['db']

nameservers = get_nameservers(db)
if ip_address in nameservers:
ctx.fail(f"{ip_address} nameserver is already configured")

if len(nameservers) >= NAMESERVERS_MAX_NUM:
ctx.fail(f"The maximum number ({NAMESERVERS_MAX_NUM}) of nameservers exceeded.")

db.set_entry('DNS_NAMESERVER', ip_address, {})

# dns nameserver delete
@nameserver.command('del')
@click.argument('ip_address_str', metavar='<ip_address>', required=True)
@click.pass_context
def del_dns_nameserver(ctx, ip_address_str):
"""Delete static DNS nameserver entry"""

ip_address = to_ip_address(ip_address_str)
if not ip_address:
ctx.fail(f"{ip_address_str} invalid nameserver ip address")

db = ctx.obj['db']

nameservers = get_nameservers(db)
if ip_address not in nameservers:
ctx.fail(f"DNS nameserver {ip_address} is not configured")

db.set_entry('DNS_NAMESERVER', ip_address, None)
Loading

0 comments on commit fc63cac

Please sign in to comment.