summaryrefslogtreecommitdiffstats
path: root/examples/ipsec-secgw
diff options
context:
space:
mode:
Diffstat (limited to 'examples/ipsec-secgw')
-rw-r--r--examples/ipsec-secgw/Makefile1
-rw-r--r--examples/ipsec-secgw/ep0.cfg160
-rw-r--r--examples/ipsec-secgw/ep1.cfg160
-rw-r--r--examples/ipsec-secgw/esp.c144
-rw-r--r--examples/ipsec-secgw/ipsec-secgw.c61
-rw-r--r--examples/ipsec-secgw/ipsec.c1
-rw-r--r--examples/ipsec-secgw/ipsec.h49
-rw-r--r--examples/ipsec-secgw/parser.c591
-rw-r--r--examples/ipsec-secgw/parser.h116
-rw-r--r--examples/ipsec-secgw/rt.c255
-rw-r--r--examples/ipsec-secgw/sa.c778
-rw-r--r--examples/ipsec-secgw/sp4.c538
-rw-r--r--examples/ipsec-secgw/sp6.c539
13 files changed, 2527 insertions, 866 deletions
diff --git a/examples/ipsec-secgw/Makefile b/examples/ipsec-secgw/Makefile
index 06b6db1e..17e91551 100644
--- a/examples/ipsec-secgw/Makefile
+++ b/examples/ipsec-secgw/Makefile
@@ -53,6 +53,7 @@ endif
#
# all source are stored in SRCS-y
#
+SRCS-y += parser.c
SRCS-y += ipsec.c
SRCS-y += esp.c
SRCS-y += sp4.c
diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
new file mode 100644
index 00000000..299aa9e0
--- /dev/null
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -0,0 +1,160 @@
+###########################################################################
+# IPSEC-SECGW Endpoint sample configuration
+#
+# The main purpose of this file is to show how to configure two systems
+# back-to-back that would forward traffic through an IPsec tunnel. This
+# file is the Endpoint 0 configuration. To use this configuration file,
+# add the following command-line option:
+#
+# -f ./ep0.cfg
+#
+###########################################################################
+
+#SP IPv4 rules
+sp ipv4 out esp protect 5 pri 1 dst 192.168.105.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 6 pri 1 dst 192.168.106.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 10 pri 1 dst 192.168.175.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 11 pri 1 dst 192.168.176.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 15 pri 1 dst 192.168.200.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 16 pri 1 dst 192.168.201.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 25 pri 1 dst 192.168.55.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 26 pri 1 dst 192.168.56.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 dst 192.168.240.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 dst 192.168.241.0/24 sport 0:65535 dport 0:65535
+
+sp ipv4 in esp protect 105 pri 1 dst 192.168.115.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 106 pri 1 dst 192.168.116.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 110 pri 1 dst 192.168.185.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 dst 192.168.245.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 dst 192.168.246.0/24 sport 0:65535 dport 0:65535
+
+#SP IPv6 rules
+sp ipv6 out esp protect 5 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 6 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 10 pri 1 dst 0000:0000:1111:1111:0000:0000:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 11 pri 1 dst 0000:0000:1111:1111:1111:1111:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 25 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 26 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sport 0:65535 dport 0:65535
+
+sp ipv6 in esp protect 15 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 16 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 110 pri 1 dst ffff:0000:1111:1111:0000:0000:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 111 pri 1 dst ffff:0000:1111:1111:1111:1111:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sport 0:65535 dport 0:65535
+
+#SA rules
+sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5
+
+sa out 6 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
+
+sa out 10 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
+
+sa out 11 cipher_algo aes-128-cbc cipher_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2 auth_algo sha1-hmac auth_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2:b2:b2:b2:b2 mode transport
+
+sa out 15 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.1.5 \
+dst 172.16.2.5
+
+sa out 16 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.1.6 \
+dst 172.16.2.6
+
+sa out 25 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:5555 \
+dst 2222:2222:2222:2222:2222:2222:2222:5555
+
+sa out 26 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:6666 \
+dst 2222:2222:2222:2222:2222:2222:2222:6666
+
+sa in 105 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
+
+sa in 106 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
+sa in 110 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
+
+sa in 111 cipher_algo aes-128-cbc cipher_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2 auth_algo sha1-hmac auth_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2:b2:b2:b2:b2 mode transport
+
+sa in 115 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.5 \
+dst 172.16.1.5
+
+sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
+sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:5555 \
+dst 1111:1111:1111:1111:1111:1111:1111:5555
+
+sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:6666 \
+dst 1111:1111:1111:1111:1111:1111:1111:6666
+
+#Routing rules
+rt ipv4 dst 172.16.2.5/32 port 0
+rt ipv4 dst 172.16.2.6/32 port 1
+rt ipv4 dst 192.168.175.0/24 port 0
+rt ipv4 dst 192.168.176.0/24 port 1
+rt ipv4 dst 192.168.240.0/24 port 0
+rt ipv4 dst 192.168.241.0/24 port 1
+rt ipv4 dst 192.168.115.0/24 port 2
+rt ipv4 dst 192.168.116.0/24 port 3
+rt ipv4 dst 192.168.65.0/24 port 2
+rt ipv4 dst 192.168.66.0/24 port 3
+rt ipv4 dst 192.168.185.0/24 port 2
+rt ipv4 dst 192.168.186.0/24 port 3
+rt ipv4 dst 192.168.210.0/24 port 2
+rt ipv4 dst 192.168.211.0/24 port 3
+rt ipv4 dst 192.168.245.0/24 port 2
+rt ipv4 dst 192.168.246.0/24 port 3
+
+rt ipv6 dst 2222:2222:2222:2222:2222:2222:2222:5555/116 port 0
+rt ipv6 dst 2222:2222:2222:2222:2222:2222:2222:6666/116 port 1
+rt ipv6 dst 0000:0000:1111:1111:0000:0000:0000:0000/116 port 0
+rt ipv6 dst 0000:0000:1111:1111:1111:1111:0000:0000/116 port 1
+rt ipv6 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/116 port 2
+rt ipv6 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/116 port 3
+rt ipv6 dst ffff:0000:0000:0000:5555:5555:0000:0000/116 port 2
+rt ipv6 dst ffff:0000:0000:0000:6666:6666:0000:0000/116 port 3
+rt ipv6 dst ffff:0000:1111:1111:0000:0000:0000:0000/116 port 2
+rt ipv6 dst ffff:0000:1111:1111:1111:1111:0000:0000/116 port 3
diff --git a/examples/ipsec-secgw/ep1.cfg b/examples/ipsec-secgw/ep1.cfg
new file mode 100644
index 00000000..3f6ff811
--- /dev/null
+++ b/examples/ipsec-secgw/ep1.cfg
@@ -0,0 +1,160 @@
+###########################################################################
+# IPSEC-SECGW Endpoint1 sample configuration
+#
+# The main purpose of this file is to show how to configure two systems
+# back-to-back that would forward traffic through an IPsec tunnel. This
+# file is the Endpoint1 configuration. To use this configuration file,
+# add the following command-line option:
+#
+# -f ./ep1.cfg
+#
+###########################################################################
+
+#SP IPv4 rules
+sp ipv4 in esp protect 5 pri 1 dst 192.168.105.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 6 pri 1 dst 192.168.106.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 10 pri 1 dst 192.168.175.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 11 pri 1 dst 192.168.176.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 15 pri 1 dst 192.168.200.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 16 pri 1 dst 192.168.201.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 25 pri 1 dst 192.168.55.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 26 pri 1 dst 192.168.56.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass dst 192.168.240.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass dst 192.168.241.0/24 sport 0:65535 dport 0:65535
+
+sp ipv4 out esp protect 105 pri 1 dst 192.168.115.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 106 pri 1 dst 192.168.116.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 110 pri 1 dst 192.168.185.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 dst 192.168.245.0/24 sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 dst 192.168.246.0/24 sport 0:65535 dport 0:65535
+
+#SP IPv6 rules
+sp ipv6 in esp protect 5 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 6 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 10 pri 1 dst 0000:0000:1111:1111:0000:0000:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 11 pri 1 dst 0000:0000:1111:1111:1111:1111:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 25 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 26 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sport 0:65535 dport 0:65535
+
+sp ipv6 out esp protect 15 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 16 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 110 pri 1 dst ffff:0000:1111:1111:0000:0000:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 111 pri 1 dst ffff:0000:1111:1111:1111:1111:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sport 0:65535 dport 0:65535
+
+#SA rules
+sa in 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5
+
+sa in 6 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
+
+sa in 10 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
+
+sa in 11 cipher_algo aes-128-cbc cipher_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2 auth_algo sha1-hmac auth_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2:b2:b2:b2:b2 mode transport
+
+sa in 15 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.1.5 \
+dst 172.16.2.5
+
+sa in 16 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.1.6 \
+dst 172.16.2.6
+
+sa in 25 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:5555 \
+dst 2222:2222:2222:2222:2222:2222:2222:5555
+
+sa in 26 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:6666 \
+dst 2222:2222:2222:2222:2222:2222:2222:6666
+
+sa out 105 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
+
+sa out 106 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
+sa out 110 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
+a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
+
+sa out 111 cipher_algo aes-128-cbc cipher_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2 auth_algo sha1-hmac auth_key b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:b2:\
+b2:b2:b2:b2:b2:b2:b2:b2:b2 mode transport
+
+sa out 115 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.5 \
+dst 172.16.1.5
+
+sa out 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
+sa out 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:5555 \
+dst 1111:1111:1111:1111:1111:1111:1111:5555
+
+sa out 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:6666 \
+dst 1111:1111:1111:1111:1111:1111:1111:6666
+
+#Routing rules
+rt ipv4 dst 172.16.1.5/32 port 0
+rt ipv4 dst 172.16.1.6/32 port 1
+rt ipv4 dst 192.168.185.0/24 port 0
+rt ipv4 dst 192.168.186.0/24 port 1
+rt ipv4 dst 192.168.245.0/24 port 0
+rt ipv4 dst 192.168.246.0/24 port 1
+rt ipv4 dst 192.168.105.0/24 port 2
+rt ipv4 dst 192.168.106.0/24 port 3
+rt ipv4 dst 192.168.55.0/24 port 2
+rt ipv4 dst 192.168.56.0/24 port 3
+rt ipv4 dst 192.168.175.0/24 port 2
+rt ipv4 dst 192.168.176.0/24 port 3
+rt ipv4 dst 192.168.200.0/24 port 2
+rt ipv4 dst 192.168.201.0/24 port 3
+rt ipv4 dst 192.168.240.0/24 port 2
+rt ipv4 dst 192.168.241.0/24 port 3
+
+rt ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 0
+rt ipv6 dst 1111:1111:1111:1111:1111:1111:1111:6666/116 port 1
+rt ipv6 dst ffff:0000:1111:1111:0000:0000:0000:0000/116 port 0
+rt ipv6 dst ffff:0000:1111:1111:1111:1111:0000:0000/116 port 1
+rt ipv6 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/116 port 2
+rt ipv6 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/116 port 3
+rt ipv6 dst 0000:0000:0000:0000:5555:5555:0000:0000/116 port 2
+rt ipv6 dst 0000:0000:0000:0000:6666:6666:0000:0000/116 port 3
+rt ipv6 dst 0000:0000:1111:1111:0000:0000:0000:0000/116 port 2
+rt ipv6 dst 0000:0000:1111:1111:1111:1111:0000:0000/116 port 3
diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c
index 05caa77a..ec5a2e62 100644
--- a/examples/ipsec-secgw/esp.c
+++ b/examples/ipsec-secgw/esp.c
@@ -50,21 +50,6 @@
#include "esp.h"
#include "ipip.h"
-static inline void
-random_iv_u64(uint64_t *buf, uint16_t n)
-{
- uint32_t left = n & 0x7;
- uint32_t i;
-
- RTE_ASSERT((n & 0x3) == 0);
-
- for (i = 0; i < (n >> 3); i++)
- buf[i] = rte_rand();
-
- if (left)
- *((uint32_t *)&buf[i]) = (uint32_t)lrand48();
-}
-
int
esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop)
@@ -98,22 +83,62 @@ esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,
return -EINVAL;
}
- sym_cop = (struct rte_crypto_sym_op *)(cop + 1);
+ sym_cop = get_sym_cop(cop);
sym_cop->m_src = m;
sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) +
sa->iv_len;
sym_cop->cipher.data.length = payload_len;
- sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, void*,
- ip_hdr_len + sizeof(struct esp_hdr));
- sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
- ip_hdr_len + sizeof(struct esp_hdr));
- sym_cop->cipher.iv.length = sa->iv_len;
+ struct cnt_blk *icb;
+ uint8_t *aad;
+ uint8_t *iv = RTE_PTR_ADD(ip4, ip_hdr_len + sizeof(struct esp_hdr));
+
+ switch (sa->cipher_algo) {
+ case RTE_CRYPTO_CIPHER_NULL:
+ case RTE_CRYPTO_CIPHER_AES_CBC:
+ sym_cop->cipher.iv.data = iv;
+ sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
+ ip_hdr_len + sizeof(struct esp_hdr));
+ sym_cop->cipher.iv.length = sa->iv_len;
+ break;
+ case RTE_CRYPTO_CIPHER_AES_CTR:
+ case RTE_CRYPTO_CIPHER_AES_GCM:
+ icb = get_cnt_blk(m);
+ icb->salt = sa->salt;
+ memcpy(&icb->iv, iv, 8);
+ icb->cnt = rte_cpu_to_be_32(1);
+ sym_cop->cipher.iv.data = (uint8_t *)icb;
+ sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
+ (uint8_t *)icb - rte_pktmbuf_mtod(m, uint8_t *));
+ sym_cop->cipher.iv.length = 16;
+ break;
+ default:
+ RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n",
+ sa->cipher_algo);
+ return -EINVAL;
+ }
- sym_cop->auth.data.offset = ip_hdr_len;
- sym_cop->auth.data.length = sizeof(struct esp_hdr) +
- sa->iv_len + payload_len;
+ switch (sa->auth_algo) {
+ case RTE_CRYPTO_AUTH_NULL:
+ case RTE_CRYPTO_AUTH_SHA1_HMAC:
+ sym_cop->auth.data.offset = ip_hdr_len;
+ sym_cop->auth.data.length = sizeof(struct esp_hdr) +
+ sa->iv_len + payload_len;
+ break;
+ case RTE_CRYPTO_AUTH_AES_GCM:
+ aad = get_aad(m);
+ memcpy(aad, iv - sizeof(struct esp_hdr), 8);
+ sym_cop->auth.aad.data = aad;
+ sym_cop->auth.aad.phys_addr = rte_pktmbuf_mtophys_offset(m,
+ aad - rte_pktmbuf_mtod(m, uint8_t *));
+ sym_cop->auth.aad.length = 8;
+ break;
+ default:
+ RTE_LOG(ERR, IPSEC_ESP, "unsupported auth algorithm %u\n",
+ sa->auth_algo);
+ return -EINVAL;
+ }
sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, void*,
rte_pktmbuf_pkt_len(m) - sa->digest_len);
@@ -282,10 +307,32 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
sa->seq++;
esp->spi = rte_cpu_to_be_32(sa->spi);
- esp->seq = rte_cpu_to_be_32(sa->seq);
+ esp->seq = rte_cpu_to_be_32((uint32_t)sa->seq);
- if (sa->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC)
- random_iv_u64((uint64_t *)(esp + 1), sa->iv_len);
+ uint64_t *iv = (uint64_t *)(esp + 1);
+
+ sym_cop = get_sym_cop(cop);
+ sym_cop->m_src = m;
+ switch (sa->cipher_algo) {
+ case RTE_CRYPTO_CIPHER_NULL:
+ case RTE_CRYPTO_CIPHER_AES_CBC:
+ memset(iv, 0, sa->iv_len);
+ sym_cop->cipher.data.offset = ip_hdr_len +
+ sizeof(struct esp_hdr);
+ sym_cop->cipher.data.length = pad_payload_len + sa->iv_len;
+ break;
+ case RTE_CRYPTO_CIPHER_AES_CTR:
+ case RTE_CRYPTO_CIPHER_AES_GCM:
+ *iv = sa->seq;
+ sym_cop->cipher.data.offset = ip_hdr_len +
+ sizeof(struct esp_hdr) + sa->iv_len;
+ sym_cop->cipher.data.length = pad_payload_len;
+ break;
+ default:
+ RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n",
+ sa->cipher_algo);
+ return -EINVAL;
+ }
/* Fill pad_len using default sequential scheme */
for (i = 0; i < pad_len - 2; i++)
@@ -293,22 +340,37 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
padding[pad_len - 2] = pad_len - 2;
padding[pad_len - 1] = nlp;
- sym_cop = (struct rte_crypto_sym_op *)(cop + 1);
-
- sym_cop->m_src = m;
- sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) +
- sa->iv_len;
- sym_cop->cipher.data.length = pad_payload_len;
-
- sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, uint8_t *,
- ip_hdr_len + sizeof(struct esp_hdr));
+ struct cnt_blk *icb = get_cnt_blk(m);
+ icb->salt = sa->salt;
+ icb->iv = sa->seq;
+ icb->cnt = rte_cpu_to_be_32(1);
+ sym_cop->cipher.iv.data = (uint8_t *)icb;
sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
- ip_hdr_len + sizeof(struct esp_hdr));
- sym_cop->cipher.iv.length = sa->iv_len;
+ (uint8_t *)icb - rte_pktmbuf_mtod(m, uint8_t *));
+ sym_cop->cipher.iv.length = 16;
- sym_cop->auth.data.offset = ip_hdr_len;
- sym_cop->auth.data.length = sizeof(struct esp_hdr) + sa->iv_len +
- pad_payload_len;
+ uint8_t *aad;
+
+ switch (sa->auth_algo) {
+ case RTE_CRYPTO_AUTH_NULL:
+ case RTE_CRYPTO_AUTH_SHA1_HMAC:
+ sym_cop->auth.data.offset = ip_hdr_len;
+ sym_cop->auth.data.length = sizeof(struct esp_hdr) +
+ sa->iv_len + pad_payload_len;
+ break;
+ case RTE_CRYPTO_AUTH_AES_GCM:
+ aad = get_aad(m);
+ memcpy(aad, esp, 8);
+ sym_cop->auth.aad.data = aad;
+ sym_cop->auth.aad.phys_addr = rte_pktmbuf_mtophys_offset(m,
+ aad - rte_pktmbuf_mtod(m, uint8_t *));
+ sym_cop->auth.aad.length = 8;
+ break;
+ default:
+ RTE_LOG(ERR, IPSEC_ESP, "unsupported auth algorithm %u\n",
+ sa->auth_algo);
+ return -EINVAL;
+ }
sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, uint8_t *,
rte_pktmbuf_pkt_len(m) - sa->digest_len);
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 266ae205..5a4c9b71 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -72,6 +72,7 @@
#include <rte_cryptodev.h>
#include "ipsec.h"
+#include "parser.h"
#define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
@@ -81,6 +82,7 @@
#define NB_MBUF (32000)
+#define CDEV_QUEUE_DESC 2048
#define CDEV_MAP_ENTRIES 1024
#define CDEV_MP_NB_OBJS 2048
#define CDEV_MP_CACHE_SZ 64
@@ -88,8 +90,6 @@
#define OPTION_CONFIG "config"
#define OPTION_SINGLE_SA "single-sa"
-#define OPTION_EP0 "ep0"
-#define OPTION_EP1 "ep1"
#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
@@ -158,7 +158,6 @@ static uint32_t enabled_port_mask;
static uint32_t unprotected_port_mask;
static int32_t promiscuous_on = 1;
static int32_t numa_on = 1; /**< NUMA is enabled by default. */
-static int32_t ep = -1; /**< Endpoint configuration (0 or 1) */
static uint32_t nb_lcores;
static uint32_t single_sa;
static uint32_t single_sa_idx;
@@ -838,7 +837,7 @@ print_usage(const char *prgname)
{
printf("%s [EAL options] -- -p PORTMASK -P -u PORTMASK"
" --"OPTION_CONFIG" (port,queue,lcore)[,(port,queue,lcore]"
- " --single-sa SAIDX --ep0|--ep1\n"
+ " --single-sa SAIDX -f CONFIG_FILE\n"
" -p PORTMASK: hexadecimal bitmask of ports to configure\n"
" -P : enable promiscuous mode\n"
" -u PORTMASK: hexadecimal bitmask of unprotected ports\n"
@@ -846,8 +845,8 @@ print_usage(const char *prgname)
"rx queues configuration\n"
" --single-sa SAIDX: use single SA index for outbound, "
"bypassing the SP\n"
- " --ep0: Configure as Endpoint 0\n"
- " --ep1: Configure as Endpoint 1\n", prgname);
+ " -f CONFIG_FILE: Configuration file path\n",
+ prgname);
}
static int32_t
@@ -960,18 +959,6 @@ parse_args_long_options(struct option *lgopts, int32_t option_index)
}
}
- if (__STRNCMP(optname, OPTION_EP0)) {
- printf("endpoint 0\n");
- ep = 0;
- ret = 0;
- }
-
- if (__STRNCMP(optname, OPTION_EP1)) {
- printf("endpoint 1\n");
- ep = 1;
- ret = 0;
- }
-
return ret;
}
#undef __STRNCMP
@@ -986,14 +973,13 @@ parse_args(int32_t argc, char **argv)
static struct option lgopts[] = {
{OPTION_CONFIG, 1, 0, 0},
{OPTION_SINGLE_SA, 1, 0, 0},
- {OPTION_EP0, 0, 0, 0},
- {OPTION_EP1, 0, 0, 0},
{NULL, 0, 0, 0}
};
+ int32_t f_present = 0;
argvopt = argv;
- while ((opt = getopt_long(argc, argvopt, "p:Pu:",
+ while ((opt = getopt_long(argc, argvopt, "p:Pu:f:",
lgopts, &option_index)) != EOF) {
switch (opt) {
@@ -1017,6 +1003,21 @@ parse_args(int32_t argc, char **argv)
return -1;
}
break;
+ case 'f':
+ if (f_present == 1) {
+ printf("\"-f\" option present more than "
+ "once!\n");
+ print_usage(prgname);
+ return -1;
+ }
+ if (parse_cfg_file(optarg) < 0) {
+ printf("parsing file \"%s\" failed\n",
+ optarg);
+ print_usage(prgname);
+ return -1;
+ }
+ f_present = 1;
+ break;
case 0:
if (parse_args_long_options(lgopts, option_index)) {
print_usage(prgname);
@@ -1029,6 +1030,11 @@ parse_args(int32_t argc, char **argv)
}
}
+ if (f_present == 0) {
+ printf("Mandatory option \"-f\" not present\n");
+ return -1;
+ }
+
if (optind >= 0)
argv[optind-1] = prgname;
@@ -1267,7 +1273,7 @@ cryptodevs_init(void)
rte_panic("Failed to initialize crypodev %u\n",
cdev_id);
- qp_conf.nb_descriptors = CDEV_MP_NB_OBJS;
+ qp_conf.nb_descriptors = CDEV_QUEUE_DESC;
for (qp = 0; qp < dev_conf.nb_queue_pairs; qp++)
if (rte_cryptodev_queue_pair_setup(cdev_id, qp,
&qp_conf, dev_conf.socket_id))
@@ -1411,9 +1417,6 @@ main(int32_t argc, char **argv)
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid parameters\n");
- if (ep < 0)
- rte_exit(EXIT_FAILURE, "need to choose either EP0 or EP1\n");
-
if ((unprotected_port_mask & enabled_port_mask) !=
unprotected_port_mask)
rte_exit(EXIT_FAILURE, "Invalid unprotected portmask 0x%x\n",
@@ -1443,13 +1446,13 @@ main(int32_t argc, char **argv)
if (socket_ctx[socket_id].mbuf_pool)
continue;
- sa_init(&socket_ctx[socket_id], socket_id, ep);
+ sa_init(&socket_ctx[socket_id], socket_id);
- sp4_init(&socket_ctx[socket_id], socket_id, ep);
+ sp4_init(&socket_ctx[socket_id], socket_id);
- sp6_init(&socket_ctx[socket_id], socket_id, ep);
+ sp6_init(&socket_ctx[socket_id], socket_id);
- rt_init(&socket_ctx[socket_id], socket_id, ep);
+ rt_init(&socket_ctx[socket_id], socket_id);
pool_init(&socket_ctx[socket_id], socket_id, NB_MBUF);
}
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 1e87d0df..f49143b9 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -124,6 +124,7 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,
priv->sa = sa;
priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
+ priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
rte_prefetch0(&priv->sym_cop);
priv->cop.sym = &priv->sym_cop;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index a442a74a..dbc8c2cb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -90,11 +90,14 @@ struct ip_addr {
} ip;
};
+#define MAX_KEY_SIZE 20
+
struct ipsec_sa {
uint32_t spi;
uint32_t cdev_id_qp;
+ uint64_t seq;
+ uint32_t salt;
struct rte_cryptodev_sym_session *crypto_session;
- uint32_t seq;
enum rte_crypto_cipher_algorithm cipher_algo;
enum rte_crypto_auth_algorithm auth_algo;
uint16_t digest_len;
@@ -106,14 +109,20 @@ struct ipsec_sa {
#define TRANSPORT (1 << 2)
struct ip_addr src;
struct ip_addr dst;
+ uint8_t cipher_key[MAX_KEY_SIZE];
+ uint16_t cipher_key_len;
+ uint8_t auth_key[MAX_KEY_SIZE];
+ uint16_t auth_key_len;
+ uint16_t aad_len;
struct rte_crypto_sym_xform *xforms;
} __rte_cache_aligned;
struct ipsec_mbuf_metadata {
+ uint8_t buf[32];
struct ipsec_sa *sa;
struct rte_crypto_op cop;
struct rte_crypto_sym_op sym_cop;
-};
+} __rte_cache_aligned;
struct cdev_qp {
uint16_t id;
@@ -151,6 +160,12 @@ struct socket_ctx {
struct rte_mempool *mbuf_pool;
};
+struct cnt_blk {
+ uint32_t salt;
+ uint64_t iv;
+ uint32_t cnt;
+} __attribute__((packed));
+
uint16_t
ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
uint16_t nb_pkts, uint16_t len);
@@ -171,6 +186,28 @@ get_priv(struct rte_mbuf *m)
return RTE_PTR_ADD(m, sizeof(struct rte_mbuf));
}
+static inline void *
+get_cnt_blk(struct rte_mbuf *m)
+{
+ struct ipsec_mbuf_metadata *priv = get_priv(m);
+
+ return &priv->buf[0];
+}
+
+static inline void *
+get_aad(struct rte_mbuf *m)
+{
+ struct ipsec_mbuf_metadata *priv = get_priv(m);
+
+ return &priv->buf[16];
+}
+
+static inline void *
+get_sym_cop(struct rte_crypto_op *cop)
+{
+ return (cop + 1);
+}
+
int
inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx);
@@ -183,15 +220,15 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
struct ipsec_sa *sa[], uint16_t nb_pkts);
void
-sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
+sp4_init(struct socket_ctx *ctx, int32_t socket_id);
void
-sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
+sp6_init(struct socket_ctx *ctx, int32_t socket_id);
void
-sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
+sa_init(struct socket_ctx *ctx, int32_t socket_id);
void
-rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
+rt_init(struct socket_ctx *ctx, int32_t socket_id);
#endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
new file mode 100644
index 00000000..9d0ea462
--- /dev/null
+++ b/examples/ipsec-secgw/parser.c
@@ -0,0 +1,591 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <rte_common.h>
+#include <rte_crypto.h>
+
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include "ipsec.h"
+#include "parser.h"
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+static int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+ uint32_t i;
+
+ if ((string == NULL) ||
+ (tokens == NULL) ||
+ (*n_tokens < 1))
+ return -EINVAL;
+
+ for (i = 0; i < *n_tokens; i++) {
+ tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+ if (tokens[i] == NULL)
+ break;
+ }
+
+ if ((i == *n_tokens) &&
+ (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
+ return -E2BIG;
+
+ *n_tokens = i;
+ return 0;
+}
+
+#define INADDRSZ 4
+#define IN6ADDRSZ 16
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return 0;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return 0;
+ saw_digit = 1;
+ }
+ *tp = (unsigned char)new;
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return 0;
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return 0;
+ }
+ if (octets < 4)
+ return 0;
+
+ memcpy(dst, tmp, INADDRSZ);
+ return 1;
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
+ const char *xdigits = 0, *curtok = 0;
+ int ch = 0, saw_xdigit = 0, count_xdigit = 0;
+ unsigned int val = 0;
+ unsigned dbloct_count = 0;
+
+ memset((tp = tmp), '\0', IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return 0;
+ curtok = src;
+ saw_xdigit = count_xdigit = 0;
+ val = 0;
+
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr((xdigits = xdigits_l), ch);
+ if (pch == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ if (count_xdigit >= 4)
+ return 0;
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return 0;
+ saw_xdigit = 1;
+ count_xdigit++;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return 0;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return 0;
+ }
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char) ((val >> 8) & 0xff);
+ *tp++ = (unsigned char) (val & 0xff);
+ saw_xdigit = 0;
+ count_xdigit = 0;
+ val = 0;
+ dbloct_count++;
+ continue;
+ }
+ if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ dbloct_count += 2;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return 0;
+ }
+ if (saw_xdigit) {
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char) ((val >> 8) & 0xff);
+ *tp++ = (unsigned char) (val & 0xff);
+ dbloct_count++;
+ }
+ if (colonp != NULL) {
+ /* if we already have 8 double octets, having a colon
+ * means error */
+ if (dbloct_count == 8)
+ return 0;
+
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[-i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return 0;
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return 1;
+}
+
+int
+parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
+{
+ char ip_str[256] = {0};
+ char *pch;
+
+ pch = strchr(token, '/');
+ if (pch != NULL) {
+ strncpy(ip_str, token, pch - token);
+ pch += 1;
+ if (is_str_num(pch) != 0)
+ return -EINVAL;
+ if (mask)
+ *mask = atoi(pch);
+ } else {
+ strncpy(ip_str, token, sizeof(ip_str) - 1);
+ if (mask)
+ *mask = 0;
+ }
+
+ if (strlen(ip_str) >= INET_ADDRSTRLEN)
+ return -EINVAL;
+
+ if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
+{
+ char ip_str[256] = {0};
+ char *pch;
+
+ pch = strchr(token, '/');
+ if (pch != NULL) {
+ strncpy(ip_str, token, pch - token);
+ pch += 1;
+ if (is_str_num(pch) != 0)
+ return -EINVAL;
+ if (mask)
+ *mask = atoi(pch);
+ } else {
+ strncpy(ip_str, token, sizeof(ip_str) - 1);
+ if (mask)
+ *mask = 0;
+ }
+
+ if (strlen(ip_str) >= INET6_ADDRSTRLEN)
+ return -EINVAL;
+
+ if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+parse_range(const char *token, uint16_t *low, uint16_t *high)
+{
+ char ch;
+ char num_str[20];
+ uint32_t pos;
+ int range_low = -1;
+ int range_high = -1;
+
+ if (!low || !high)
+ return -1;
+
+ memset(num_str, 0, 20);
+ pos = 0;
+
+ while ((ch = *token++) != '\0') {
+ if (isdigit(ch)) {
+ if (pos >= 19)
+ return -1;
+ num_str[pos++] = ch;
+ } else if (ch == ':') {
+ if (range_low != -1)
+ return -1;
+ range_low = atoi(num_str);
+ memset(num_str, 0, 20);
+ pos = 0;
+ }
+ }
+
+ if (strlen(num_str) == 0)
+ return -1;
+
+ range_high = atoi(num_str);
+
+ *low = (uint16_t)range_low;
+ *high = (uint16_t)range_high;
+
+ return 0;
+}
+
+/** sp add parse */
+struct cfg_sp_add_cfg_item {
+ cmdline_fixed_string_t sp_keyword;
+ cmdline_multi_string_t multi_string;
+};
+
+static void
+cfg_sp_add_cfg_item_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, void *data)
+{
+ struct cfg_sp_add_cfg_item *params = parsed_result;
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ struct parse_status *status = (struct parse_status *)data;
+
+ APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
+ &n_tokens) == 0), status, "too many arguments");
+
+ if (status->status < 0)
+ return;
+
+ if (strcmp(tokens[0], "ipv4") == 0) {
+ parse_sp4_tokens(tokens, n_tokens, status);
+ if (status->status < 0)
+ return;
+ } else if (strcmp(tokens[0], "ipv6") == 0) {
+ parse_sp6_tokens(tokens, n_tokens, status);
+ if (status->status < 0)
+ return;
+ } else {
+ APP_CHECK(0, status, "unrecognizable input %s\n",
+ tokens[0]);
+ return;
+ }
+}
+
+static cmdline_parse_token_string_t cfg_sp_add_sp_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
+ sp_keyword, "sp");
+
+static cmdline_parse_token_string_t cfg_sp_add_multi_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
+ TOKEN_STRING_MULTI);
+
+cmdline_parse_inst_t cfg_sp_add_rule = {
+ .f = cfg_sp_add_cfg_item_parsed,
+ .data = NULL,
+ .help_str = "",
+ .tokens = {
+ (void *) &cfg_sp_add_sp_str,
+ (void *) &cfg_sp_add_multi_str,
+ NULL,
+ },
+};
+
+/* sa add parse */
+struct cfg_sa_add_cfg_item {
+ cmdline_fixed_string_t sa_keyword;
+ cmdline_multi_string_t multi_string;
+};
+
+static void
+cfg_sa_add_cfg_item_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, void *data)
+{
+ struct cfg_sa_add_cfg_item *params = parsed_result;
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ struct parse_status *status = (struct parse_status *)data;
+
+ APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
+ &n_tokens) == 0, status, "too many arguments\n");
+
+ parse_sa_tokens(tokens, n_tokens, status);
+}
+
+static cmdline_parse_token_string_t cfg_sa_add_sa_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
+ sa_keyword, "sa");
+
+static cmdline_parse_token_string_t cfg_sa_add_multi_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
+ TOKEN_STRING_MULTI);
+
+cmdline_parse_inst_t cfg_sa_add_rule = {
+ .f = cfg_sa_add_cfg_item_parsed,
+ .data = NULL,
+ .help_str = "",
+ .tokens = {
+ (void *) &cfg_sa_add_sa_str,
+ (void *) &cfg_sa_add_multi_str,
+ NULL,
+ },
+};
+
+/* rt add parse */
+struct cfg_rt_add_cfg_item {
+ cmdline_fixed_string_t rt_keyword;
+ cmdline_multi_string_t multi_string;
+};
+
+static void
+cfg_rt_add_cfg_item_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, void *data)
+{
+ struct cfg_rt_add_cfg_item *params = parsed_result;
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ struct parse_status *status = (struct parse_status *)data;
+
+ APP_CHECK(parse_tokenize_string(
+ params->multi_string, tokens, &n_tokens) == 0,
+ status, "too many arguments\n");
+ if (status->status < 0)
+ return;
+
+ parse_rt_tokens(tokens, n_tokens, status);
+}
+
+static cmdline_parse_token_string_t cfg_rt_add_rt_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
+ rt_keyword, "rt");
+
+static cmdline_parse_token_string_t cfg_rt_add_multi_str =
+ TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
+ TOKEN_STRING_MULTI);
+
+cmdline_parse_inst_t cfg_rt_add_rule = {
+ .f = cfg_rt_add_cfg_item_parsed,
+ .data = NULL,
+ .help_str = "",
+ .tokens = {
+ (void *) &cfg_rt_add_rt_str,
+ (void *) &cfg_rt_add_multi_str,
+ NULL,
+ },
+};
+
+/** set of cfg items */
+cmdline_parse_ctx_t ipsec_ctx[] = {
+ (cmdline_parse_inst_t *)&cfg_sp_add_rule,
+ (cmdline_parse_inst_t *)&cfg_sa_add_rule,
+ (cmdline_parse_inst_t *)&cfg_rt_add_rule,
+ NULL,
+};
+
+int
+parse_cfg_file(const char *cfg_filename)
+{
+ struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
+ FILE *f = fopen(cfg_filename, "r");
+ char str[1024] = {0}, *get_s = NULL;
+ uint32_t line_num = 0;
+ struct parse_status status = {0};
+
+ if (f == NULL) {
+ rte_panic("Error: invalid file descriptor %s\n", cfg_filename);
+ goto error_exit;
+ }
+
+ if (cl == NULL) {
+ rte_panic("Error: cannot create cmdline instance\n");
+ goto error_exit;
+ }
+
+ cfg_sp_add_rule.data = &status;
+ cfg_sa_add_rule.data = &status;
+ cfg_rt_add_rule.data = &status;
+
+ do {
+ char oneline[1024];
+ char *pos;
+ get_s = fgets(oneline, 1024, f);
+
+ if (!get_s)
+ break;
+
+ line_num++;
+
+ if (strlen(oneline) > 1022) {
+ rte_panic("%s:%u: error: "
+ "the line contains more characters the parser can handle\n",
+ cfg_filename, line_num);
+ goto error_exit;
+ }
+
+ /* process comment char '#' */
+ if (oneline[0] == '#')
+ continue;
+
+ pos = strchr(oneline, '#');
+ if (pos != NULL)
+ *pos = '\0';
+
+ /* process line concatenator '\' */
+ pos = strchr(oneline, 92);
+ if (pos != NULL) {
+ if (pos != oneline+strlen(oneline) - 2) {
+ rte_panic("%s:%u: error: "
+ "no character should exist after '\\'\n",
+ cfg_filename, line_num);
+ goto error_exit;
+ }
+
+ *pos = '\0';
+
+ if (strlen(oneline) + strlen(str) > 1022) {
+ rte_panic("%s:%u: error: "
+ "the concatenated line contains more characters the parser can handle\n",
+ cfg_filename, line_num);
+ goto error_exit;
+ }
+
+ strncpy(str + strlen(str), oneline,
+ strlen(oneline));
+
+ continue;
+ }
+
+ /* copy the line to str and process */
+ if (strlen(oneline) + strlen(str) > 1022) {
+ rte_panic("%s:%u: error: "
+ "the line contains more characters the parser can handle\n",
+ cfg_filename, line_num);
+ goto error_exit;
+ }
+ strncpy(str + strlen(str), oneline,
+ strlen(oneline));
+
+ str[strlen(str)] = '\n';
+ if (cmdline_parse(cl, str) < 0) {
+ rte_panic("%s:%u: error: parsing \"%s\" failed\n",
+ cfg_filename, line_num, str);
+ goto error_exit;
+ }
+
+ if (status.status < 0) {
+ rte_panic("%s:%u: error: %s", cfg_filename,
+ line_num, status.parse_msg);
+ goto error_exit;
+ }
+
+ memset(str, 0, 1024);
+ } while (1);
+
+ cmdline_stdin_exit(cl);
+ fclose(f);
+
+ return 0;
+
+error_exit:
+ if (cl)
+ cmdline_stdin_exit(cl);
+ if (f)
+ fclose(f);
+
+ return -1;
+}
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
new file mode 100644
index 00000000..d31ae016
--- /dev/null
+++ b/examples/ipsec-secgw/parser.h
@@ -0,0 +1,116 @@
+/* BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#ifndef __PARSER_H
+#define __PARSER_H
+
+struct parse_status {
+ int status;
+ char parse_msg[256];
+};
+
+#define APP_CHECK(exp, status, fmt, ...) \
+do { \
+ if (!(exp)) { \
+ sprintf(status->parse_msg, fmt "\n", \
+ ## __VA_ARGS__); \
+ status->status = -1; \
+ } else \
+ status->status = 0; \
+} while (0)
+
+#define APP_CHECK_PRESENCE(val, str, status) \
+ APP_CHECK(val == 0, status, \
+ "item \"%s\" already present", str)
+
+#define APP_CHECK_TOKEN_EQUAL(tokens, index, ref, status) \
+ APP_CHECK(strcmp(tokens[index], ref) == 0, status, \
+ "unrecognized input \"%s\": expect \"%s\"\n", \
+ tokens[index], ref)
+
+static inline int
+is_str_num(const char *str)
+{
+ uint32_t i;
+
+ for (i = 0; i < strlen(str); i++)
+ if (!isdigit(str[i]))
+ return -1;
+
+ return 0;
+}
+
+#define APP_CHECK_TOKEN_IS_NUM(tokens, index, status) \
+ APP_CHECK(is_str_num(tokens[index]) == 0, status, \
+ "input \"%s\" is not valid number string", tokens[index])
+
+
+#define INCREMENT_TOKEN_INDEX(index, max_num, status) \
+do { \
+ APP_CHECK(index + 1 < max_num, status, "reaching the end of " \
+ "the token array"); \
+ index++; \
+} while (0)
+
+int
+parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask);
+
+int
+parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask);
+
+int
+parse_range(const char *token, uint16_t *low, uint16_t *high);
+
+void
+parse_sp4_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status);
+
+void
+parse_sp6_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status);
+
+void
+parse_sa_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status);
+
+void
+parse_rt_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status);
+
+int
+parse_cfg_file(const char *cfg_filename);
+
+#endif
diff --git a/examples/ipsec-secgw/rt.c b/examples/ipsec-secgw/rt.c
index fa5f0420..e03c5f0b 100644
--- a/examples/ipsec-secgw/rt.c
+++ b/examples/ipsec-secgw/rt.c
@@ -41,6 +41,7 @@
#include <rte_ip.h>
#include "ipsec.h"
+#include "parser.h"
#define RT_IPV4_MAX_RULES 1024
#define RT_IPV6_MAX_RULES 1024
@@ -57,135 +58,106 @@ struct ip6_route {
uint8_t if_out;
};
-static struct ip4_route rt_ip4_ep0[] = {
- /* Outbound */
- /* Tunnels */
- { IPv4(172, 16, 2, 5), 32, 0 },
- { IPv4(172, 16, 2, 6), 32, 1 },
- /* Transport */
- { IPv4(192, 168, 175, 0), 24, 0 },
- { IPv4(192, 168, 176, 0), 24, 1 },
- /* Bypass */
- { IPv4(192, 168, 240, 0), 24, 0 },
- { IPv4(192, 168, 241, 0), 24, 1 },
+struct ip4_route rt_ip4[RT_IPV4_MAX_RULES];
+uint32_t nb_rt_ip4;
- /* Inbound */
- /* Tunnels */
- { IPv4(192, 168, 115, 0), 24, 2 },
- { IPv4(192, 168, 116, 0), 24, 3 },
- { IPv4(192, 168, 65, 0), 24, 2 },
- { IPv4(192, 168, 66, 0), 24, 3 },
- /* Transport */
- { IPv4(192, 168, 185, 0), 24, 2 },
- { IPv4(192, 168, 186, 0), 24, 3 },
- /* NULL */
- { IPv4(192, 168, 210, 0), 24, 2 },
- { IPv4(192, 168, 211, 0), 24, 3 },
- /* Bypass */
- { IPv4(192, 168, 245, 0), 24, 2 },
- { IPv4(192, 168, 246, 0), 24, 3 },
-};
-
-static struct ip6_route rt_ip6_ep0[] = {
- /* Outbound */
- /* Tunnels */
- { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 }, 116, 0 },
- { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 }, 116, 1 },
- /* Transport */
- { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
- { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
- /* Inbound */
- /* Tunnels */
- { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
- 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
- 0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
- { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
- 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
- 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
- /* Transport */
- { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
-};
-
-static struct ip4_route rt_ip4_ep1[] = {
- /* Outbound */
- /* Tunnels */
- { IPv4(172, 16, 1, 5), 32, 0 },
- { IPv4(172, 16, 1, 6), 32, 1 },
- /* Transport */
- { IPv4(192, 168, 185, 0), 24, 0 },
- { IPv4(192, 168, 186, 0), 24, 1 },
- /* Bypass */
- { IPv4(192, 168, 245, 0), 24, 0 },
- { IPv4(192, 168, 246, 0), 24, 1 },
+struct ip6_route rt_ip6[RT_IPV4_MAX_RULES];
+uint32_t nb_rt_ip6;
- /* Inbound */
- /* Tunnels */
- { IPv4(192, 168, 105, 0), 24, 2 },
- { IPv4(192, 168, 106, 0), 24, 3 },
- { IPv4(192, 168, 55, 0), 24, 2 },
- { IPv4(192, 168, 56, 0), 24, 3 },
- /* Transport */
- { IPv4(192, 168, 175, 0), 24, 2 },
- { IPv4(192, 168, 176, 0), 24, 3 },
- /* NULL */
- { IPv4(192, 168, 200, 0), 24, 2 },
- { IPv4(192, 168, 201, 0), 24, 3 },
- /* Bypass */
- { IPv4(192, 168, 240, 0), 24, 2 },
- { IPv4(192, 168, 241, 0), 24, 3 },
-};
+void
+parse_rt_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status)
+{
+ uint32_t ti;
+ uint32_t *n_rts = NULL;
+ struct ip4_route *route_ipv4 = NULL;
+ struct ip6_route *route_ipv6 = NULL;
+
+ if (strcmp(tokens[0], "ipv4") == 0) {
+ n_rts = &nb_rt_ip4;
+ route_ipv4 = &rt_ip4[*n_rts];
+
+ APP_CHECK(*n_rts <= RT_IPV4_MAX_RULES - 1, status,
+ "too many rt rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ } else if (strcmp(tokens[0], "ipv6") == 0) {
+ n_rts = &nb_rt_ip6;
+ route_ipv6 = &rt_ip6[*n_rts];
+
+ APP_CHECK(*n_rts <= RT_IPV6_MAX_RULES - 1, status,
+ "too many rt rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+ } else {
+ APP_CHECK(0, status, "unrecognized input \"%s\"",
+ tokens[0]);
+ return;
+ }
-static struct ip6_route rt_ip6_ep1[] = {
- /* Outbound */
- /* Tunnels */
- { { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 }, 116, 0 },
- { { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 }, 116, 1 },
- /* Transport */
- { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
- { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
+ for (ti = 1; ti < n_tokens; ti++) {
+ if (strcmp(tokens[ti], "dst") == 0) {
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (route_ipv4 != NULL) {
+ struct in_addr ip;
+ uint32_t depth = 0;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti],
+ &ip, &depth) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ route_ipv4->ip = rte_bswap32(
+ (uint32_t)ip.s_addr);
+ route_ipv4->depth = (uint8_t)depth;
+ } else {
+ struct in6_addr ip;
+ uint32_t depth;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti],
+ &ip, &depth) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv6 address",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ memcpy(route_ipv6->ip, ip.s6_addr, 16);
+ route_ipv6->depth = (uint8_t)depth;
+ }
+ }
+
+ if (strcmp(tokens[ti], "port") == 0) {
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+ if (status->status < 0)
+ return;
+ if (route_ipv4 != NULL)
+ route_ipv4->if_out = atoi(tokens[ti]);
+ else
+ route_ipv6->if_out = atoi(tokens[ti]);
+ }
+ }
- /* Inbound */
- /* Tunnels */
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
- 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
- 0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
- 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
- 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
- /* Transport */
- { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
- { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
-};
+ *n_rts = *n_rts + 1;
+}
void
-rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
+rt_init(struct socket_ctx *ctx, int32_t socket_id)
{
char name[PATH_MAX];
uint32_t i;
int32_t ret;
struct rte_lpm *lpm;
struct rte_lpm6 *lpm6;
- struct ip4_route *rt;
- struct ip6_route *rt6;
char a, b, c, d;
- uint32_t nb_routes, nb_routes6;
struct rte_lpm_config conf = { 0 };
struct rte_lpm6_config conf6 = { 0 };
@@ -200,23 +172,12 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
rte_exit(EXIT_FAILURE, "IPv6 Routing Table for socket %u "
"already initialized\n", socket_id);
+ if (nb_rt_ip4 == 0 && nb_rt_ip6 == 0)
+ RTE_LOG(WARNING, IPSEC, "No Routing rule specified\n");
+
printf("Creating IPv4 Routing Table (RT) context with %u max routes\n",
RT_IPV4_MAX_RULES);
- if (ep == 0) {
- rt = rt_ip4_ep0;
- nb_routes = RTE_DIM(rt_ip4_ep0);
- rt6 = rt_ip6_ep0;
- nb_routes6 = RTE_DIM(rt_ip6_ep0);
- } else if (ep == 1) {
- rt = rt_ip4_ep1;
- nb_routes = RTE_DIM(rt_ip4_ep1);
- rt6 = rt_ip6_ep1;
- nb_routes6 = RTE_DIM(rt_ip6_ep1);
- } else
- rte_exit(EXIT_FAILURE, "Invalid EP value %u. Only 0 or 1 "
- "supported.\n", ep);
-
/* create the LPM table */
snprintf(name, sizeof(name), "%s_%u", "rt_ip4", socket_id);
conf.max_rules = RT_IPV4_MAX_RULES;
@@ -227,15 +188,17 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
"on socket %d\n", name, socket_id);
/* populate the LPM table */
- for (i = 0; i < nb_routes; i++) {
- ret = rte_lpm_add(lpm, rt[i].ip, rt[i].depth, rt[i].if_out);
+ for (i = 0; i < nb_rt_ip4; i++) {
+ ret = rte_lpm_add(lpm, rt_ip4[i].ip, rt_ip4[i].depth,
+ rt_ip4[i].if_out);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
"LPM table on socket %d\n", i, name, socket_id);
- uint32_t_to_char(rt[i].ip, &a, &b, &c, &d);
+ uint32_t_to_char(rt_ip4[i].ip, &a, &b, &c, &d);
printf("LPM: Adding route %hhu.%hhu.%hhu.%hhu/%hhu (%hhu)\n",
- a, b, c, d, rt[i].depth, rt[i].if_out);
+ a, b, c, d, rt_ip4[i].depth,
+ rt_ip4[i].if_out);
}
snprintf(name, sizeof(name), "%s_%u", "rt_ip6", socket_id);
@@ -247,24 +210,24 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
"on socket %d\n", name, socket_id);
/* populate the LPM table */
- for (i = 0; i < nb_routes6; i++) {
- ret = rte_lpm6_add(lpm6, rt6[i].ip, rt6[i].depth,
- rt6[i].if_out);
+ for (i = 0; i < nb_rt_ip6; i++) {
+ ret = rte_lpm6_add(lpm6, rt_ip6[i].ip, rt_ip6[i].depth,
+ rt_ip6[i].if_out);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
"LPM table on socket %d\n", i, name, socket_id);
printf("LPM6: Adding route "
" %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hhx (%hhx)\n",
- (uint16_t)((rt6[i].ip[0] << 8) | rt6[i].ip[1]),
- (uint16_t)((rt6[i].ip[2] << 8) | rt6[i].ip[3]),
- (uint16_t)((rt6[i].ip[4] << 8) | rt6[i].ip[5]),
- (uint16_t)((rt6[i].ip[6] << 8) | rt6[i].ip[7]),
- (uint16_t)((rt6[i].ip[8] << 8) | rt6[i].ip[9]),
- (uint16_t)((rt6[i].ip[10] << 8) | rt6[i].ip[11]),
- (uint16_t)((rt6[i].ip[12] << 8) | rt6[i].ip[13]),
- (uint16_t)((rt6[i].ip[14] << 8) | rt6[i].ip[15]),
- rt6[i].depth, rt6[i].if_out);
+ (uint16_t)((rt_ip6[i].ip[0] << 8) | rt_ip6[i].ip[1]),
+ (uint16_t)((rt_ip6[i].ip[2] << 8) | rt_ip6[i].ip[3]),
+ (uint16_t)((rt_ip6[i].ip[4] << 8) | rt_ip6[i].ip[5]),
+ (uint16_t)((rt_ip6[i].ip[6] << 8) | rt_ip6[i].ip[7]),
+ (uint16_t)((rt_ip6[i].ip[8] << 8) | rt_ip6[i].ip[9]),
+ (uint16_t)((rt_ip6[i].ip[10] << 8) | rt_ip6[i].ip[11]),
+ (uint16_t)((rt_ip6[i].ip[12] << 8) | rt_ip6[i].ip[13]),
+ (uint16_t)((rt_ip6[i].ip[14] << 8) | rt_ip6[i].ip[15]),
+ rt_ip6[i].depth, rt_ip6[i].if_out);
}
ctx->rt_ip4 = (struct rt_ctx *)lpm;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 4439e0f5..8c4406cf 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -45,246 +45,501 @@
#include <rte_byteorder.h>
#include <rte_errno.h>
#include <rte_ip.h>
+#include <rte_random.h>
#include "ipsec.h"
#include "esp.h"
+#include "parser.h"
+
+struct supported_cipher_algo {
+ const char *keyword;
+ enum rte_crypto_cipher_algorithm algo;
+ uint16_t iv_len;
+ uint16_t block_size;
+ uint16_t key_len;
+};
-/* SAs Outbound */
-const struct ipsec_sa sa_out[] = {
- {
- .spi = 5,
- .src.ip.ip4 = IPv4(172, 16, 1, 5),
- .dst.ip.ip4 = IPv4(172, 16, 2, 5),
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP4_TUNNEL
- },
- {
- .spi = 6,
- .src.ip.ip4 = IPv4(172, 16, 1, 6),
- .dst.ip.ip4 = IPv4(172, 16, 2, 6),
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP4_TUNNEL
- },
- {
- .spi = 10,
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = TRANSPORT
- },
- {
- .spi = 11,
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = TRANSPORT
- },
- {
- .spi = 15,
- .src.ip.ip4 = IPv4(172, 16, 1, 5),
- .dst.ip.ip4 = IPv4(172, 16, 2, 5),
- .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
- .auth_algo = RTE_CRYPTO_AUTH_NULL,
- .digest_len = 0,
- .iv_len = 0,
- .block_size = 4,
- .flags = IP4_TUNNEL
- },
- {
- .spi = 16,
- .src.ip.ip4 = IPv4(172, 16, 1, 6),
- .dst.ip.ip4 = IPv4(172, 16, 2, 6),
- .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
- .auth_algo = RTE_CRYPTO_AUTH_NULL,
- .digest_len = 0,
- .iv_len = 0,
- .block_size = 4,
- .flags = IP4_TUNNEL
- },
- {
- .spi = 25,
- .src.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
- .dst.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP6_TUNNEL
- },
- {
- .spi = 26,
- .src.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
- .dst.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP6_TUNNEL
- },
+struct supported_auth_algo {
+ const char *keyword;
+ enum rte_crypto_auth_algorithm algo;
+ uint16_t digest_len;
+ uint16_t key_len;
+ uint8_t aad_len;
+ uint8_t key_not_req;
};
-/* SAs Inbound */
-const struct ipsec_sa sa_in[] = {
- {
- .spi = 105,
- .src.ip.ip4 = IPv4(172, 16, 2, 5),
- .dst.ip.ip4 = IPv4(172, 16, 1, 5),
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP4_TUNNEL
- },
+const struct supported_cipher_algo cipher_algos[] = {
{
- .spi = 106,
- .src.ip.ip4 = IPv4(172, 16, 2, 6),
- .dst.ip.ip4 = IPv4(172, 16, 1, 6),
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP4_TUNNEL
+ .keyword = "null",
+ .algo = RTE_CRYPTO_CIPHER_NULL,
+ .iv_len = 0,
+ .block_size = 4,
+ .key_len = 0
},
{
- .spi = 110,
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = TRANSPORT
+ .keyword = "aes-128-cbc",
+ .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .iv_len = 16,
+ .block_size = 16,
+ .key_len = 16
},
{
- .spi = 111,
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = TRANSPORT
+ .keyword = "aes-128-gcm",
+ .algo = RTE_CRYPTO_CIPHER_AES_GCM,
+ .iv_len = 8,
+ .block_size = 4,
+ .key_len = 20
},
{
- .spi = 115,
- .src.ip.ip4 = IPv4(172, 16, 2, 5),
- .dst.ip.ip4 = IPv4(172, 16, 1, 5),
- .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
- .auth_algo = RTE_CRYPTO_AUTH_NULL,
- .digest_len = 0,
- .iv_len = 0,
- .block_size = 4,
- .flags = IP4_TUNNEL
- },
+ .keyword = "aes-128-ctr",
+ .algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .iv_len = 8,
+ .block_size = 16, /* XXX AESNI MB limition, should be 4 */
+ .key_len = 20
+ }
+};
+
+const struct supported_auth_algo auth_algos[] = {
{
- .spi = 116,
- .src.ip.ip4 = IPv4(172, 16, 2, 6),
- .dst.ip.ip4 = IPv4(172, 16, 1, 6),
- .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
- .auth_algo = RTE_CRYPTO_AUTH_NULL,
- .digest_len = 0,
- .iv_len = 0,
- .block_size = 4,
- .flags = IP4_TUNNEL
+ .keyword = "null",
+ .algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .key_len = 0,
+ .key_not_req = 1
},
{
- .spi = 125,
- .src.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
- .dst.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP6_TUNNEL
+ .keyword = "sha1-hmac",
+ .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .key_len = 20
},
{
- .spi = 126,
- .src.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
- .dst.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
- .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
- .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
- .digest_len = 12,
- .iv_len = 16,
- .block_size = 16,
- .flags = IP6_TUNNEL
- },
+ .keyword = "aes-128-gcm",
+ .algo = RTE_CRYPTO_AUTH_AES_GCM,
+ .digest_len = 16,
+ .aad_len = 8,
+ .key_not_req = 1
+ }
};
-static uint8_t cipher_key[256] = "sixteenbytes key";
+struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+uint32_t nb_sa_out;
+
+struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
+uint32_t nb_sa_in;
+
+static const struct supported_cipher_algo *
+find_match_cipher_algo(const char *cipher_keyword)
+{
+ size_t i;
-/* AES CBC xform */
-const struct rte_crypto_sym_xform aescbc_enc_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_CIPHER,
- {.cipher = { RTE_CRYPTO_CIPHER_OP_ENCRYPT, RTE_CRYPTO_CIPHER_AES_CBC,
- .key = { cipher_key, 16 } }
+ for (i = 0; i < RTE_DIM(cipher_algos); i++) {
+ const struct supported_cipher_algo *algo =
+ &cipher_algos[i];
+
+ if (strcmp(cipher_keyword, algo->keyword) == 0)
+ return algo;
}
-};
-const struct rte_crypto_sym_xform aescbc_dec_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_CIPHER,
- {.cipher = { RTE_CRYPTO_CIPHER_OP_DECRYPT, RTE_CRYPTO_CIPHER_AES_CBC,
- .key = { cipher_key, 16 } }
+ return NULL;
+}
+
+static const struct supported_auth_algo *
+find_match_auth_algo(const char *auth_keyword)
+{
+ size_t i;
+
+ for (i = 0; i < RTE_DIM(auth_algos); i++) {
+ const struct supported_auth_algo *algo =
+ &auth_algos[i];
+
+ if (strcmp(auth_keyword, algo->keyword) == 0)
+ return algo;
}
-};
-static uint8_t auth_key[256] = "twentybytes hash key";
+ return NULL;
+}
-/* SHA1 HMAC xform */
-const struct rte_crypto_sym_xform sha1hmac_gen_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_AUTH,
- {.auth = { RTE_CRYPTO_AUTH_OP_GENERATE, RTE_CRYPTO_AUTH_SHA1_HMAC,
- .key = { auth_key, 20 }, 12, 0 }
+/** parse_key_string
+ * parse x:x:x:x.... hex number key string into uint8_t *key
+ * return:
+ * > 0: number of bytes parsed
+ * 0: failed
+ */
+static uint32_t
+parse_key_string(const char *key_str, uint8_t *key)
+{
+ const char *pt_start = key_str, *pt_end = key_str;
+ uint32_t nb_bytes = 0;
+
+ while (pt_end != NULL) {
+ char sub_str[3] = {0};
+
+ pt_end = strchr(pt_start, ':');
+
+ if (pt_end == NULL) {
+ if (strlen(pt_start) > 2)
+ return 0;
+ strncpy(sub_str, pt_start, 2);
+ } else {
+ if (pt_end - pt_start > 2)
+ return 0;
+
+ strncpy(sub_str, pt_start, pt_end - pt_start);
+ pt_start = pt_end + 1;
+ }
+
+ key[nb_bytes++] = strtol(sub_str, NULL, 16);
}
-};
-const struct rte_crypto_sym_xform sha1hmac_verify_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_AUTH,
- {.auth = { RTE_CRYPTO_AUTH_OP_VERIFY, RTE_CRYPTO_AUTH_SHA1_HMAC,
- .key = { auth_key, 20 }, 12, 0 }
+ return nb_bytes;
+}
+
+void
+parse_sa_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status)
+{
+ struct ipsec_sa *rule = NULL;
+ uint32_t ti; /*token index*/
+ uint32_t *ri /*rule index*/;
+ uint32_t cipher_algo_p = 0;
+ uint32_t auth_algo_p = 0;
+ uint32_t src_p = 0;
+ uint32_t dst_p = 0;
+ uint32_t mode_p = 0;
+
+ if (strcmp(tokens[0], "in") == 0) {
+ ri = &nb_sa_in;
+
+ APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
+ "too many sa rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule = &sa_in[*ri];
+ } else {
+ ri = &nb_sa_out;
+
+ APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
+ "too many sa rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule = &sa_out[*ri];
}
-};
-/* AES CBC xform */
-const struct rte_crypto_sym_xform null_cipher_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_CIPHER,
- {.cipher = { .algo = RTE_CRYPTO_CIPHER_NULL }
+ /* spi number */
+ APP_CHECK_TOKEN_IS_NUM(tokens, 1, status);
+ if (status->status < 0)
+ return;
+ rule->spi = atoi(tokens[1]);
+
+ for (ti = 2; ti < n_tokens; ti++) {
+ if (strcmp(tokens[ti], "mode") == 0) {
+ APP_CHECK_PRESENCE(mode_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (strcmp(tokens[ti], "ipv4-tunnel") == 0)
+ rule->flags = IP4_TUNNEL;
+ else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+ rule->flags = IP6_TUNNEL;
+ else if (strcmp(tokens[ti], "transport") == 0)
+ rule->flags = TRANSPORT;
+ else {
+ APP_CHECK(0, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+ return;
+ }
+
+ mode_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "cipher_algo") == 0) {
+ const struct supported_cipher_algo *algo;
+ uint32_t key_len;
+
+ APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti],
+ status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ algo = find_match_cipher_algo(tokens[ti]);
+
+ APP_CHECK(algo != NULL, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+
+ rule->cipher_algo = algo->algo;
+ rule->block_size = algo->block_size;
+ rule->iv_len = algo->iv_len;
+ rule->cipher_key_len = algo->key_len;
+
+ /* for NULL algorithm, no cipher key required */
+ if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ cipher_algo_p = 1;
+ continue;
+ }
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0,
+ status, "unrecognized input \"%s\", "
+ "expect \"cipher_key\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ key_len = parse_key_string(tokens[ti],
+ rule->cipher_key);
+ APP_CHECK(key_len == rule->cipher_key_len, status,
+ "unrecognized input \"%s\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ if (algo->algo == RTE_CRYPTO_CIPHER_AES_CBC)
+ rule->salt = (uint32_t)rte_rand();
+
+ if ((algo->algo == RTE_CRYPTO_CIPHER_AES_CTR) ||
+ (algo->algo == RTE_CRYPTO_CIPHER_AES_GCM)) {
+ key_len -= 4;
+ rule->cipher_key_len = key_len;
+ memcpy(&rule->salt,
+ &rule->cipher_key[key_len], 4);
+ }
+
+ cipher_algo_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "auth_algo") == 0) {
+ const struct supported_auth_algo *algo;
+ uint32_t key_len;
+
+ APP_CHECK_PRESENCE(auth_algo_p, tokens[ti],
+ status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ algo = find_match_auth_algo(tokens[ti]);
+ APP_CHECK(algo != NULL, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+
+ rule->auth_algo = algo->algo;
+ rule->auth_key_len = algo->key_len;
+ rule->digest_len = algo->digest_len;
+ rule->aad_len = algo->key_len;
+
+ /* NULL algorithm and combined algos do not
+ * require auth key
+ */
+ if (algo->key_not_req) {
+ auth_algo_p = 1;
+ continue;
+ }
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(strcmp(tokens[ti], "auth_key") == 0,
+ status, "unrecognized input \"%s\", "
+ "expect \"auth_key\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ key_len = parse_key_string(tokens[ti],
+ rule->auth_key);
+ APP_CHECK(key_len == rule->auth_key_len, status,
+ "unrecognized input \"%s\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ auth_algo_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "src") == 0) {
+ APP_CHECK_PRESENCE(src_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (rule->flags == IP4_TUNNEL) {
+ struct in_addr ip;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti],
+ &ip, NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ rule->src.ip.ip4 = rte_bswap32(
+ (uint32_t)ip.s_addr);
+ } else if (rule->flags == IP6_TUNNEL) {
+ struct in6_addr ip;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv6 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ memcpy(rule->src.ip.ip6.ip6_b,
+ ip.s6_addr, 16);
+ } else if (rule->flags == TRANSPORT) {
+ APP_CHECK(0, status, "unrecognized input "
+ "\"%s\"", tokens[ti]);
+ return;
+ }
+
+ src_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dst") == 0) {
+ APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (rule->flags == IP4_TUNNEL) {
+ struct in_addr ip;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti],
+ &ip, NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ rule->dst.ip.ip4 = rte_bswap32(
+ (uint32_t)ip.s_addr);
+ } else if (rule->flags == IP6_TUNNEL) {
+ struct in6_addr ip;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv6 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ memcpy(rule->dst.ip.ip6.ip6_b, ip.s6_addr, 16);
+ } else if (rule->flags == TRANSPORT) {
+ APP_CHECK(0, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+ return;
+ }
+
+ dst_p = 1;
+ continue;
+ }
+
+ /* unrecognizeable input */
+ APP_CHECK(0, status, "unrecognized input \"%s\"",
+ tokens[ti]);
+ return;
}
-};
-const struct rte_crypto_sym_xform null_auth_xf = {
- NULL,
- RTE_CRYPTO_SYM_XFORM_AUTH,
- {.auth = { .algo = RTE_CRYPTO_AUTH_NULL }
+ APP_CHECK(cipher_algo_p == 1, status, "missing cipher options");
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(auth_algo_p == 1, status, "missing auth options");
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(mode_p == 1, status, "missing mode option");
+ if (status->status < 0)
+ return;
+
+ *ri = *ri + 1;
+}
+
+static inline void
+print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
+{
+ uint32_t i;
+ uint8_t a, b, c, d;
+
+ printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi);
+
+ for (i = 0; i < RTE_DIM(cipher_algos); i++) {
+ if (cipher_algos[i].algo == sa->cipher_algo) {
+ printf("%s ", cipher_algos[i].keyword);
+ break;
+ }
}
-};
+
+ for (i = 0; i < RTE_DIM(auth_algos); i++) {
+ if (auth_algos[i].algo == sa->auth_algo) {
+ printf("%s ", auth_algos[i].keyword);
+ break;
+ }
+ }
+
+ printf("mode:");
+
+ switch (sa->flags) {
+ case IP4_TUNNEL:
+ printf("IP4Tunnel ");
+ uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d);
+ printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a);
+ uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d);
+ printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a);
+ break;
+ case IP6_TUNNEL:
+ printf("IP6Tunnel ");
+ for (i = 0; i < 16; i++) {
+ if (i % 2 && i != 15)
+ printf("%.2x:", sa->src.ip.ip6.ip6_b[i]);
+ else
+ printf("%.2x", sa->src.ip.ip6.ip6_b[i]);
+ }
+ printf(" ");
+ for (i = 0; i < 16; i++) {
+ if (i % 2 && i != 15)
+ printf("%.2x:", sa->dst.ip.ip6.ip6_b[i]);
+ else
+ printf("%.2x", sa->dst.ip.ip6.ip6_b[i]);
+ }
+ break;
+ case TRANSPORT:
+ printf("Transport");
+ break;
+ }
+ printf("\n");
+}
struct sa_ctx {
struct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES];
@@ -347,25 +602,55 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
}
if (inbound) {
- if (sa->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
- sa_ctx->xf[idx].a = null_auth_xf;
- sa_ctx->xf[idx].b = null_cipher_xf;
- } else {
- sa_ctx->xf[idx].a = sha1hmac_verify_xf;
- sa_ctx->xf[idx].b = aescbc_dec_xf;
- }
+ sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
+ sa_ctx->xf[idx].b.cipher.key.data = sa->cipher_key;
+ sa_ctx->xf[idx].b.cipher.key.length =
+ sa->cipher_key_len;
+ sa_ctx->xf[idx].b.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ sa_ctx->xf[idx].b.next = NULL;
+
+ sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ sa_ctx->xf[idx].a.auth.algo = sa->auth_algo;
+ sa_ctx->xf[idx].a.auth.add_auth_data_length =
+ sa->aad_len;
+ sa_ctx->xf[idx].a.auth.key.data = sa->auth_key;
+ sa_ctx->xf[idx].a.auth.key.length =
+ sa->auth_key_len;
+ sa_ctx->xf[idx].a.auth.digest_length =
+ sa->digest_len;
+ sa_ctx->xf[idx].a.auth.op =
+ RTE_CRYPTO_AUTH_OP_VERIFY;
+
} else { /* outbound */
- if (sa->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
- sa_ctx->xf[idx].a = null_cipher_xf;
- sa_ctx->xf[idx].b = null_auth_xf;
- } else {
- sa_ctx->xf[idx].a = aescbc_enc_xf;
- sa_ctx->xf[idx].b = sha1hmac_gen_xf;
- }
+ sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
+ sa_ctx->xf[idx].a.cipher.key.data = sa->cipher_key;
+ sa_ctx->xf[idx].a.cipher.key.length =
+ sa->cipher_key_len;
+ sa_ctx->xf[idx].a.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ sa_ctx->xf[idx].a.next = NULL;
+
+ sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ sa_ctx->xf[idx].b.auth.algo = sa->auth_algo;
+ sa_ctx->xf[idx].b.auth.add_auth_data_length =
+ sa->aad_len;
+ sa_ctx->xf[idx].b.auth.key.data = sa->auth_key;
+ sa_ctx->xf[idx].b.auth.key.length =
+ sa->auth_key_len;
+ sa_ctx->xf[idx].b.auth.digest_length =
+ sa->digest_len;
+ sa_ctx->xf[idx].b.auth.op =
+ RTE_CRYPTO_AUTH_OP_GENERATE;
}
+
sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
sa_ctx->xf[idx].b.next = NULL;
sa->xforms = &sa_ctx->xf[idx].a;
+
+ print_one_sa_rule(sa, inbound);
}
return 0;
@@ -386,10 +671,8 @@ sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
}
void
-sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
+sa_init(struct socket_ctx *ctx, int32_t socket_id)
{
- const struct ipsec_sa *sa_out_entries, *sa_in_entries;
- uint32_t nb_out_entries, nb_in_entries;
const char *name;
if (ctx == NULL)
@@ -403,35 +686,30 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
"initialized\n", socket_id);
- if (ep == 0) {
- sa_out_entries = sa_out;
- nb_out_entries = RTE_DIM(sa_out);
- sa_in_entries = sa_in;
- nb_in_entries = RTE_DIM(sa_in);
- } else if (ep == 1) {
- sa_out_entries = sa_in;
- nb_out_entries = RTE_DIM(sa_in);
- sa_in_entries = sa_out;
- nb_in_entries = RTE_DIM(sa_out);
- } else
- rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
- "Only 0 or 1 supported.\n", ep);
+ if (nb_sa_in > 0) {
+ name = "sa_in";
+ ctx->sa_in = sa_create(name, socket_id);
+ if (ctx->sa_in == NULL)
+ rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+ "context %s in socket %d\n", rte_errno,
+ name, socket_id);
- name = "sa_in";
- ctx->sa_in = sa_create(name, socket_id);
- if (ctx->sa_in == NULL)
- rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
- "in socket %d\n", rte_errno, name, socket_id);
-
- name = "sa_out";
- ctx->sa_out = sa_create(name, socket_id);
- if (ctx->sa_out == NULL)
- rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
- "in socket %d\n", rte_errno, name, socket_id);
+ sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in);
+ } else
+ RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n");
- sa_in_add_rules(ctx->sa_in, sa_in_entries, nb_in_entries);
+ if (nb_sa_out > 0) {
+ name = "sa_out";
+ ctx->sa_out = sa_create(name, socket_id);
+ if (ctx->sa_out == NULL)
+ rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+ "context %s in socket %d\n", rte_errno,
+ name, socket_id);
- sa_out_add_rules(ctx->sa_out, sa_out_entries, nb_out_entries);
+ sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out);
+ } else
+ RTE_LOG(WARNING, IPSEC, "No SA Outbound rule "
+ "specified\n");
}
int
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 9c4b256b..38c72a92 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -42,8 +42,9 @@
#include <rte_ip.h>
#include "ipsec.h"
+#include "parser.h"
-#define MAX_ACL_RULE_NUM 1000
+#define MAX_ACL_RULE_NUM 1024
/*
* Rule and trace formats definitions.
@@ -113,211 +114,306 @@ struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-const struct acl4_rules acl4_rules_out[] = {
- {
- .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 105, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 106, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 175, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 176, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 200, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 201, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 55, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 56, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 240, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 241, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
+uint32_t nb_acl4_rules_out;
+
+struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+uint32_t nb_acl4_rules_in;
+
+void
+parse_sp4_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status)
+{
+ struct acl4_rules *rule_ipv4 = NULL;
+
+ uint32_t *ri = NULL; /* rule index */
+ uint32_t ti = 0; /* token index */
+
+ uint32_t esp_p = 0;
+ uint32_t protect_p = 0;
+ uint32_t bypass_p = 0;
+ uint32_t discard_p = 0;
+ uint32_t pri_p = 0;
+ uint32_t src_p = 0;
+ uint32_t dst_p = 0;
+ uint32_t proto_p = 0;
+ uint32_t sport_p = 0;
+ uint32_t dport_p = 0;
+
+ if (strcmp(tokens[1], "in") == 0) {
+ ri = &nb_acl4_rules_in;
+
+ APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
+ "too many sp rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule_ipv4 = &acl4_rules_in[*ri];
+
+ } else if (strcmp(tokens[1], "out") == 0) {
+ ri = &nb_acl4_rules_out;
+
+ APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
+ "too many sp rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule_ipv4 = &acl4_rules_out[*ri];
+ } else {
+ APP_CHECK(0, status, "unrecognized input \"%s\", expect"
+ " \"in\" or \"out\"\n", tokens[ti]);
+ return;
}
-};
-const struct acl4_rules acl4_rules_in[] = {
- {
- .data = {.userdata = PROTECT(105), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 115, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(106), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 116, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 185, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 186, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(115), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 210, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(116), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 211, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 65, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 66, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 245, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
- /* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 246, 0),
- .mask_range.u32 = 24,},
- /* source port */
- .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ rule_ipv4->data.category_mask = 1;
+
+ for (ti = 2; ti < n_tokens; ti++) {
+ if (strcmp(tokens[ti], "esp") == 0) {
+ /* currently do nothing */
+ APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ esp_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "protect") == 0) {
+ APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(bypass_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "bypass");
+ if (status->status < 0)
+ return;
+ APP_CHECK(discard_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->data.userdata =
+ PROTECT(atoi(tokens[ti]));
+
+ protect_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "bypass") == 0) {
+ APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(protect_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "protect");
+ if (status->status < 0)
+ return;
+ APP_CHECK(discard_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->data.userdata = BYPASS;
+
+ bypass_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "discard") == 0) {
+ APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(protect_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "protect");
+ if (status->status < 0)
+ return;
+ APP_CHECK(bypass_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->data.userdata = DISCARD;
+
+ discard_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "pri") == 0) {
+ APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->data.priority = atoi(tokens[ti]);
+
+ pri_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "src") == 0) {
+ struct in_addr ip;
+ uint32_t depth;
+
+ APP_CHECK_PRESENCE(src_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
+ &depth) == 0, status, "unrecognized "
+ "input \"%s\", expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->field[1].value.u32 =
+ rte_bswap32(ip.s_addr);
+ rule_ipv4->field[1].mask_range.u32 =
+ depth;
+
+ src_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dst") == 0) {
+ struct in_addr ip;
+ uint32_t depth;
+
+ APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
+ &depth) == 0, status, "unrecognized "
+ "input \"%s\", expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->field[2].value.u32 =
+ rte_bswap32(ip.s_addr);
+ rule_ipv4->field[2].mask_range.u32 =
+ depth;
+
+ dst_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "proto") == 0) {
+ uint16_t low, high;
+
+ APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &low, &high)
+ == 0, status, "unrecognized input \"%s\""
+ ", expect \"from:to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+ APP_CHECK(low <= 0xff, status, "proto low "
+ "over-limit");
+ if (status->status < 0)
+ return;
+ APP_CHECK(high <= 0xff, status, "proto high "
+ "over-limit");
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->field[0].value.u8 = (uint8_t)low;
+ rule_ipv4->field[0].mask_range.u8 = (uint8_t)high;
+
+ proto_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "sport") == 0) {
+ uint16_t port_low, port_high;
+
+ APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &port_low,
+ &port_high) == 0, status, "unrecognized "
+ "input \"%s\", expect \"port_from:"
+ "port_to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->field[3].value.u16 = port_low;
+ rule_ipv4->field[3].mask_range.u16 = port_high;
+
+ sport_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dport") == 0) {
+ uint16_t port_low, port_high;
+
+ APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &port_low,
+ &port_high) == 0, status, "unrecognized "
+ "input \"%s\", expect \"port_from:"
+ "port_to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv4->field[4].value.u16 = port_low;
+ rule_ipv4->field[4].mask_range.u16 = port_high;
+
+ dport_p = 1;
+ continue;
+ }
+
+ /* unrecognizeable input */
+ APP_CHECK(0, status, "unrecognized input \"%s\"",
+ tokens[ti]);
+ return;
}
-};
+
+ /* check if argument(s) are missing */
+ APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
+ "argument \"protect\", \"bypass\", or \"discard\"");
+ if (status->status < 0)
+ return;
+
+ *ri = *ri + 1;
+}
static void
print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra)
@@ -406,11 +502,9 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
}
void
-sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
+sp4_init(struct socket_ctx *ctx, int32_t socket_id)
{
const char *name;
- const struct acl4_rules *rules_out, *rules_in;
- uint32_t nb_out_rules, nb_in_rules;
if (ctx == NULL)
rte_exit(EXIT_FAILURE, "NULL context.\n");
@@ -423,25 +517,19 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already "
"initialized\n", socket_id);
- if (ep == 0) {
- rules_out = acl4_rules_out;
- nb_out_rules = RTE_DIM(acl4_rules_out);
- rules_in = acl4_rules_in;
- nb_in_rules = RTE_DIM(acl4_rules_in);
- } else if (ep == 1) {
- rules_out = acl4_rules_in;
- nb_out_rules = RTE_DIM(acl4_rules_in);
- rules_in = acl4_rules_out;
- nb_in_rules = RTE_DIM(acl4_rules_out);
+ if (nb_acl4_rules_in > 0) {
+ name = "sp_ip4_in";
+ ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name,
+ socket_id, acl4_rules_in, nb_acl4_rules_in);
} else
- rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
- "Only 0 or 1 supported.\n", ep);
-
- name = "sp_ip4_in";
- ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, socket_id,
- rules_in, nb_in_rules);
+ RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule "
+ "specified\n");
- name = "sp_ip4_out";
- ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name, socket_id,
- rules_out, nb_out_rules);
+ if (nb_acl4_rules_out > 0) {
+ name = "sp_ip4_out";
+ ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name,
+ socket_id, acl4_rules_out, nb_acl4_rules_out);
+ } else
+ RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule "
+ "specified\n");
}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index 1dda11a4..62fb492c 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -42,8 +42,9 @@
#include <rte_ip.h>
#include "ipsec.h"
+#include "parser.h"
-#define MAX_ACL_RULE_NUM 1000
+#define MAX_ACL_RULE_NUM 1024
enum {
IP6_PROTO,
@@ -144,155 +145,363 @@ struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-const struct acl6_rules acl6_rules_out[] = {
- {
- .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+uint32_t nb_acl6_rules_out;
+
+struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+uint32_t nb_acl6_rules_in;
+
+void
+parse_sp6_tokens(char **tokens, uint32_t n_tokens,
+ struct parse_status *status)
+{
+ struct acl6_rules *rule_ipv6 = NULL;
+
+ uint32_t *ri = NULL; /* rule index */
+ uint32_t ti = 0; /* token index */
+
+ uint32_t esp_p = 0;
+ uint32_t protect_p = 0;
+ uint32_t bypass_p = 0;
+ uint32_t discard_p = 0;
+ uint32_t pri_p = 0;
+ uint32_t src_p = 0;
+ uint32_t dst_p = 0;
+ uint32_t proto_p = 0;
+ uint32_t sport_p = 0;
+ uint32_t dport_p = 0;
+
+ if (strcmp(tokens[1], "in") == 0) {
+ ri = &nb_acl6_rules_in;
+
+ APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
+ "many sp rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule_ipv6 = &acl6_rules_in[*ri];
+
+ } else if (strcmp(tokens[1], "out") == 0) {
+ ri = &nb_acl6_rules_out;
+
+ APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
+ "many sp rules, abort insertion\n");
+ if (status->status < 0)
+ return;
+
+ rule_ipv6 = &acl6_rules_out[*ri];
+
+ } else {
+ APP_CHECK(0, status, "unrecognized input \"%s\", expect"
+ " \"in\" or \"out\"\n", tokens[ti]);
+ return;
}
-};
-const struct acl6_rules acl6_rules_in[] = {
- {
- .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
- },
- {
- .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
- /* destination IPv6 */
- .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
- .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
- .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
- .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
- /* source port */
- .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
- /* destination port */
- .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ rule_ipv6->data.category_mask = 1;
+
+
+ for (ti = 2; ti < n_tokens; ti++) {
+ if (strcmp(tokens[ti], "esp") == 0) {
+ /* currently do nothing */
+ APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ esp_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "protect") == 0) {
+ APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(bypass_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "bypass");
+ if (status->status < 0)
+ return;
+ APP_CHECK(discard_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->data.userdata =
+ PROTECT(atoi(tokens[ti]));
+
+ protect_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "bypass") == 0) {
+ APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(protect_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "protect");
+ if (status->status < 0)
+ return;
+ APP_CHECK(discard_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->data.userdata = BYPASS;
+
+ bypass_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "discard") == 0) {
+ APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ APP_CHECK(protect_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "protect");
+ if (status->status < 0)
+ return;
+ APP_CHECK(bypass_p == 0, status, "conflict item "
+ "between \"%s\" and \"%s\"", tokens[ti],
+ "discard");
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->data.userdata = DISCARD;
+
+ discard_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "pri") == 0) {
+ APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+ APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->data.priority = atoi(tokens[ti]);
+
+ pri_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "src") == 0) {
+ struct in6_addr ip;
+ uint32_t depth;
+
+ APP_CHECK_PRESENCE(src_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ &depth) == 0, status, "unrecognized "
+ "input \"%s\", expect valid ipv6 "
+ "addr", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->field[1].value.u32 =
+ (uint32_t)ip.s6_addr[0] << 24 |
+ (uint32_t)ip.s6_addr[1] << 16 |
+ (uint32_t)ip.s6_addr[2] << 8 |
+ (uint32_t)ip.s6_addr[3];
+ rule_ipv6->field[1].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[2].value.u32 =
+ (uint32_t)ip.s6_addr[4] << 24 |
+ (uint32_t)ip.s6_addr[5] << 16 |
+ (uint32_t)ip.s6_addr[6] << 8 |
+ (uint32_t)ip.s6_addr[7];
+ rule_ipv6->field[2].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[3].value.u32 =
+ (uint32_t)ip.s6_addr[8] << 24 |
+ (uint32_t)ip.s6_addr[9] << 16 |
+ (uint32_t)ip.s6_addr[10] << 8 |
+ (uint32_t)ip.s6_addr[11];
+ rule_ipv6->field[3].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[4].value.u32 =
+ (uint32_t)ip.s6_addr[12] << 24 |
+ (uint32_t)ip.s6_addr[13] << 16 |
+ (uint32_t)ip.s6_addr[14] << 8 |
+ (uint32_t)ip.s6_addr[15];
+ rule_ipv6->field[4].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+
+ src_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dst") == 0) {
+ struct in6_addr ip;
+ uint32_t depth;
+
+ APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ &depth) == 0, status, "unrecognized "
+ "input \"%s\", expect valid ipv6 "
+ "addr", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->field[5].value.u32 =
+ (uint32_t)ip.s6_addr[0] << 24 |
+ (uint32_t)ip.s6_addr[1] << 16 |
+ (uint32_t)ip.s6_addr[2] << 8 |
+ (uint32_t)ip.s6_addr[3];
+ rule_ipv6->field[5].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[6].value.u32 =
+ (uint32_t)ip.s6_addr[4] << 24 |
+ (uint32_t)ip.s6_addr[5] << 16 |
+ (uint32_t)ip.s6_addr[6] << 8 |
+ (uint32_t)ip.s6_addr[7];
+ rule_ipv6->field[6].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[7].value.u32 =
+ (uint32_t)ip.s6_addr[8] << 24 |
+ (uint32_t)ip.s6_addr[9] << 16 |
+ (uint32_t)ip.s6_addr[10] << 8 |
+ (uint32_t)ip.s6_addr[11];
+ rule_ipv6->field[7].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+ depth = (depth > 32) ? (depth - 32) : 0;
+ rule_ipv6->field[8].value.u32 =
+ (uint32_t)ip.s6_addr[12] << 24 |
+ (uint32_t)ip.s6_addr[13] << 16 |
+ (uint32_t)ip.s6_addr[14] << 8 |
+ (uint32_t)ip.s6_addr[15];
+ rule_ipv6->field[8].mask_range.u32 =
+ (depth > 32) ? 32 : depth;
+
+ dst_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "proto") == 0) {
+ uint16_t low, high;
+
+ APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &low, &high)
+ == 0, status, "unrecognized input \"%s\""
+ ", expect \"from:to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+ APP_CHECK(low <= 0xff, status, "proto low "
+ "over-limit");
+ if (status->status < 0)
+ return;
+ APP_CHECK(high <= 0xff, status, "proto high "
+ "over-limit");
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->field[0].value.u8 = (uint8_t)low;
+ rule_ipv6->field[0].mask_range.u8 = (uint8_t)high;
+
+ proto_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "sport") == 0) {
+ uint16_t port_low, port_high;
+
+ APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &port_low,
+ &port_high) == 0, status, "unrecognized "
+ "input \"%s\", expect \"port_from:"
+ "port_to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->field[9].value.u16 = port_low;
+ rule_ipv6->field[9].mask_range.u16 = port_high;
+
+ sport_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dport") == 0) {
+ uint16_t port_low, port_high;
+
+ APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(parse_range(tokens[ti], &port_low,
+ &port_high) == 0, status, "unrecognized "
+ "input \"%s\", expect \"port_from:"
+ "port_to\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ rule_ipv6->field[10].value.u16 = port_low;
+ rule_ipv6->field[10].mask_range.u16 = port_high;
+
+ dport_p = 1;
+ continue;
+ }
+
+ /* unrecognizeable input */
+ APP_CHECK(0, status, "unrecognized input \"%s\"",
+ tokens[ti]);
+ return;
}
-};
+
+ /* check if argument(s) are missing */
+ APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
+ "argument \"protect\", \"bypass\", or \"discard\"");
+ if (status->status < 0)
+ return;
+
+ *ri = *ri + 1;
+}
static inline void
print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra)
@@ -407,11 +616,9 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
}
void
-sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
+sp6_init(struct socket_ctx *ctx, int32_t socket_id)
{
const char *name;
- const struct acl6_rules *rules_out, *rules_in;
- uint32_t nb_out_rules, nb_in_rules;
if (ctx == NULL)
rte_exit(EXIT_FAILURE, "NULL context.\n");
@@ -424,25 +631,19 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
"already initialized\n", socket_id);
- if (ep == 0) {
- rules_out = acl6_rules_out;
- nb_out_rules = RTE_DIM(acl6_rules_out);
- rules_in = acl6_rules_in;
- nb_in_rules = RTE_DIM(acl6_rules_in);
- } else if (ep == 1) {
- rules_out = acl6_rules_in;
- nb_out_rules = RTE_DIM(acl6_rules_in);
- rules_in = acl6_rules_out;
- nb_in_rules = RTE_DIM(acl6_rules_out);
+ if (nb_acl6_rules_in > 0) {
+ name = "sp_ip6_in";
+ ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name,
+ socket_id, acl6_rules_in, nb_acl6_rules_in);
} else
- rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
- "Only 0 or 1 supported.\n", ep);
+ RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule "
+ "specified\n");
- name = "sp_ip6_in";
- ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, socket_id,
- rules_in, nb_in_rules);
-
- name = "sp_ip6_out";
- ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, socket_id,
- rules_out, nb_out_rules);
+ if (nb_acl6_rules_out > 0) {
+ name = "sp_ip6_out";
+ ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name,
+ socket_id, acl6_rules_out, nb_acl6_rules_out);
+ } else
+ RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule "
+ "specified\n");
}