diff options
30 files changed, 510 insertions, 122 deletions
diff --git a/data/templates/accel-ppp/ipoe.config.j2 b/data/templates/accel-ppp/ipoe.config.j2 index c89812985..d87b90473 100644 --- a/data/templates/accel-ppp/ipoe.config.j2 +++ b/data/templates/accel-ppp/ipoe.config.j2 @@ -29,7 +29,9 @@ max-starting={{ max_concurrent_sessions }}  [log]  syslog=accel-ipoe,daemon  copy=1 -level=5 +{% if log.level is vyos_defined %} +level={{ log.level }} +{% endif %}  [ipoe]  verbose=1 diff --git a/data/templates/accel-ppp/l2tp.config.j2 b/data/templates/accel-ppp/l2tp.config.j2 index 4ce9042c2..db4db66a7 100644 --- a/data/templates/accel-ppp/l2tp.config.j2 +++ b/data/templates/accel-ppp/l2tp.config.j2 @@ -28,7 +28,9 @@ max-starting={{ max_concurrent_sessions }}  [log]  syslog=accel-l2tp,daemon  copy=1 -level=5 +{% if log.level is vyos_defined %} +level={{ log.level }} +{% endif %}  [client-ip-range]  0.0.0.0/0 diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2 index 42bc8440c..6711f2ec9 100644 --- a/data/templates/accel-ppp/pppoe.config.j2 +++ b/data/templates/accel-ppp/pppoe.config.j2 @@ -27,7 +27,9 @@ thread-count={{ thread_count }}  [log]  syslog=accel-pppoe,daemon  copy=1 -level=5 +{% if log.level is vyos_defined %} +level={{ log.level }} +{% endif %}  {% if authentication.mode is vyos_defined("noauth") %}  [auth] diff --git a/data/templates/accel-ppp/pptp.config.j2 b/data/templates/accel-ppp/pptp.config.j2 index a04bd40c0..44f35998b 100644 --- a/data/templates/accel-ppp/pptp.config.j2 +++ b/data/templates/accel-ppp/pptp.config.j2 @@ -28,7 +28,9 @@ max-starting={{ max_concurrent_sessions }}  [log]  syslog=accel-pptp,daemon  copy=1 -level=5 +{% if log.level is vyos_defined %} +level={{ log.level }} +{% endif %}  [client-ip-range]  0.0.0.0/0 diff --git a/data/templates/accel-ppp/sstp.config.j2 b/data/templates/accel-ppp/sstp.config.j2 index 22fb55506..38da829f3 100644 --- a/data/templates/accel-ppp/sstp.config.j2 +++ b/data/templates/accel-ppp/sstp.config.j2 @@ -29,7 +29,9 @@ max-starting={{ max_concurrent_sessions }}  [log]  syslog=accel-sstp,daemon  copy=1 -level=5 +{% if log.level is vyos_defined %} +level={{ log.level }} +{% endif %}  [client-ip-range]  0.0.0.0/0 diff --git a/data/templates/ipsec/ios_profile.j2 b/data/templates/ipsec/ios_profile.j2 index eb74924b8..a9ae1c7a9 100644 --- a/data/templates/ipsec/ios_profile.j2 +++ b/data/templates/ipsec/ios_profile.j2 @@ -83,12 +83,15 @@                  </dict>              </dict>          </dict> +{% if certs is vyos_defined %}          <!-- This payload is optional but it provides an easy way to install the CA certificate together with the configuration --> +{%     for cert in certs %} +        <!-- Payload for: {{ cert.ca_cn }} -->          <dict>              <key>PayloadIdentifier</key> -            <string>org.example.ca</string> +            <string>org.{{ cert.ca_cn | lower | replace(' ', '.') | replace('_', '.') }}</string>              <key>PayloadUUID</key> -            <string>{{ '' | get_uuid }}</string> +            <string>{{ cert.ca_cn | generate_uuid4 }}</string>              <key>PayloadType</key>              <string>com.apple.security.root</string>              <key>PayloadVersion</key> @@ -96,9 +99,11 @@              <!-- This is the Base64 (PEM) encoded CA certificate -->              <key>PayloadContent</key>              <data> -            {{ ca_cert }} +            {{ cert.ca_cert }}              </data>          </dict> +{%     endfor %} +{% endif %}      </array>  </dict>  </plist> diff --git a/interface-definitions/include/accel-ppp/log.xml.i b/interface-definitions/include/accel-ppp/log.xml.i new file mode 100644 index 000000000..96ce93ff9 --- /dev/null +++ b/interface-definitions/include/accel-ppp/log.xml.i @@ -0,0 +1,42 @@ +<!-- include start from accel-ppp/log.xml.i --> +<node name="log"> +  <properties> +    <help>Server logging </help> +  </properties> +  <children> +    <leafNode name="level"> +      <properties> +        <help>Specifies log level</help> +        <valueHelp> +          <format>0</format> +          <description>Turn off logging</description> +        </valueHelp> +        <valueHelp> +          <format>1</format> +          <description>Log only error messages</description> +        </valueHelp> +        <valueHelp> +          <format>2</format> +          <description>Log error and warning messages</description> +        </valueHelp> +        <valueHelp> +          <format>3</format> +          <description>Log error, warning and minimum information messages</description> +        </valueHelp> +        <valueHelp> +          <format>4</format> +          <description>Log error, warning and full information messages</description> +        </valueHelp> +        <valueHelp> +          <format>5</format> +          <description>Log all messages including debug messages</description> +        </valueHelp> +        <constraint> +          <validator name="numeric" argument="--range 0-5"/> +        </constraint> +      </properties> +      <defaultValue>3</defaultValue> +    </leafNode> +  </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match-group.xml.i b/interface-definitions/include/qos/class-match-group.xml.i new file mode 100644 index 000000000..40e3b7259 --- /dev/null +++ b/interface-definitions/include/qos/class-match-group.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/class-match-group.xml.i --> +<leafNode name="match-group"> +  <properties> +    <help>Filter group for QoS policy</help> +    <valueHelp> +      <format>txt</format> +      <description>Match group name</description> +    </valueHelp> +    <completionHelp> +      <script>${vyos_completion_dir}/qos/list_traffic_match_group.py</script> +    </completionHelp> +    <multi/> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match-ipv4.xml.i b/interface-definitions/include/qos/class-match-ipv4.xml.i new file mode 100644 index 000000000..dc44d32d5 --- /dev/null +++ b/interface-definitions/include/qos/class-match-ipv4.xml.i @@ -0,0 +1,31 @@ +<!-- include start from qos/class-match-ipv4.xml.i --> +<node name="ip"> +  <properties> +    <help>Match IP protocol header</help> +  </properties> +  <children> +    <node name="destination"> +      <properties> +        <help>Match on destination port or address</help> +      </properties> +      <children> +        #include <include/qos/class-match-ipv4-address.xml.i> +        #include <include/port-number.xml.i> +      </children> +    </node> +    #include <include/qos/match-dscp.xml.i> +    #include <include/qos/max-length.xml.i> +    #include <include/ip-protocol.xml.i> +    <node name="source"> +      <properties> +        <help>Match on source port or address</help> +      </properties> +      <children> +        #include <include/qos/class-match-ipv4-address.xml.i> +        #include <include/port-number.xml.i> +      </children> +    </node> +    #include <include/qos/tcp-flags.xml.i> +  </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match-ipv6.xml.i b/interface-definitions/include/qos/class-match-ipv6.xml.i new file mode 100644 index 000000000..ed7aceff9 --- /dev/null +++ b/interface-definitions/include/qos/class-match-ipv6.xml.i @@ -0,0 +1,31 @@ +<!-- include start from qos/class-match-ipv6.xml.i --> +<node name="ipv6"> +  <properties> +    <help>Match IPv6 protocol header</help> +  </properties> +  <children> +    <node name="destination"> +      <properties> +        <help>Match on destination port or address</help> +      </properties> +      <children> +        #include <include/qos/class-match-ipv6-address.xml.i> +        #include <include/port-number.xml.i> +      </children> +    </node> +    #include <include/qos/match-dscp.xml.i> +    #include <include/qos/max-length.xml.i> +    #include <include/ip-protocol.xml.i> +    <node name="source"> +      <properties> +        <help>Match on source port or address</help> +      </properties> +      <children> +        #include <include/qos/class-match-ipv6-address.xml.i> +        #include <include/port-number.xml.i> +      </children> +    </node> +    #include <include/qos/tcp-flags.xml.i> +  </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match-mark.xml.i b/interface-definitions/include/qos/class-match-mark.xml.i new file mode 100644 index 000000000..a7481c6aa --- /dev/null +++ b/interface-definitions/include/qos/class-match-mark.xml.i @@ -0,0 +1,14 @@ +<!-- include start from qos/class-match-mark.xml.i --> +<leafNode name="mark"> +  <properties> +    <help>Match on mark applied by firewall</help> +    <valueHelp> +      <format>u32</format> +      <description>FW mark to match</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 0-4294967295"/> +    </constraint> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match-vif.xml.i b/interface-definitions/include/qos/class-match-vif.xml.i new file mode 100644 index 000000000..ec58db606 --- /dev/null +++ b/interface-definitions/include/qos/class-match-vif.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/class-match-vif.xml.i --> +<leafNode name="vif"> +  <properties> +    <help>Virtual Local Area Network (VLAN) ID for this match</help> +    <valueHelp> +      <format>u32:0-4095</format> +      <description>Virtual Local Area Network (VLAN) tag </description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 0-4095"/> +    </constraint> +    <constraintErrorMessage>VLAN ID must be between 0 and 4095</constraintErrorMessage> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/class-match.xml.i b/interface-definitions/include/qos/class-match.xml.i index 4ba12f8f7..77d1933a3 100644 --- a/interface-definitions/include/qos/class-match.xml.i +++ b/interface-definitions/include/qos/class-match.xml.i @@ -5,7 +5,7 @@      <constraint>        <regex>[^-].*</regex>      </constraint> -    <constraintErrorMessage>Match queue name cannot start with hyphen (-)</constraintErrorMessage> +    <constraintErrorMessage>Match queue name cannot start with hyphen</constraintErrorMessage>    </properties>    <children>      #include <include/generic-description.xml.i> @@ -89,89 +89,10 @@        </children>      </node>      #include <include/generic-interface.xml.i> -    <node name="ip"> -      <properties> -        <help>Match IP protocol header</help> -      </properties> -      <children> -        <node name="destination"> -          <properties> -            <help>Match on destination port or address</help> -          </properties> -          <children> -            #include <include/qos/class-match-ipv4-address.xml.i> -            #include <include/port-number.xml.i> -          </children> -        </node> -        #include <include/qos/match-dscp.xml.i> -        #include <include/qos/max-length.xml.i> -        #include <include/ip-protocol.xml.i> -        <node name="source"> -          <properties> -            <help>Match on source port or address</help> -          </properties> -          <children> -            #include <include/qos/class-match-ipv4-address.xml.i> -            #include <include/port-number.xml.i> -          </children> -        </node> -        #include <include/qos/tcp-flags.xml.i> -      </children> -    </node> -    <node name="ipv6"> -      <properties> -        <help>Match IPv6 protocol header</help> -      </properties> -      <children> -        <node name="destination"> -          <properties> -            <help>Match on destination port or address</help> -          </properties> -          <children> -            #include <include/qos/class-match-ipv6-address.xml.i> -            #include <include/port-number.xml.i> -          </children> -        </node> -        #include <include/qos/match-dscp.xml.i> -        #include <include/qos/max-length.xml.i> -        #include <include/ip-protocol.xml.i> -        <node name="source"> -          <properties> -            <help>Match on source port or address</help> -          </properties> -          <children> -            #include <include/qos/class-match-ipv6-address.xml.i> -            #include <include/port-number.xml.i> -          </children> -        </node> -        #include <include/qos/tcp-flags.xml.i> -      </children> -    </node> -    <leafNode name="mark"> -      <properties> -        <help>Match on mark applied by firewall</help> -        <valueHelp> -          <format>u32</format> -          <description>FW mark to match</description> -        </valueHelp> -        <constraint> -          <validator name="numeric" argument="--range 0-4294967295"/> -        </constraint> -      </properties> -    </leafNode> -    <leafNode name="vif"> -      <properties> -        <help>Virtual Local Area Network (VLAN) ID for this match</help> -        <valueHelp> -          <format>u32:0-4095</format> -          <description>Virtual Local Area Network (VLAN) tag </description> -        </valueHelp> -        <constraint> -          <validator name="numeric" argument="--range 0-4095"/> -        </constraint> -        <constraintErrorMessage>VLAN ID must be between 0 and 4095</constraintErrorMessage> -      </properties> -    </leafNode> +    #include <include/qos/class-match-ipv4.xml.i> +    #include <include/qos/class-match-ipv6.xml.i> +    #include <include/qos/class-match-mark.xml.i> +    #include <include/qos/class-match-vif.xml.i>    </children>  </tagNode>  <!-- include end --> diff --git a/interface-definitions/include/version/reverseproxy-version.xml.i b/interface-definitions/include/version/reverseproxy-version.xml.i new file mode 100644 index 000000000..907ea1e5e --- /dev/null +++ b/interface-definitions/include/version/reverseproxy-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/reverseproxy-version.xml.i --> +<syntaxVersion component='reverse-proxy' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/load-balancing_reverse-proxy.xml.in b/interface-definitions/load-balancing_reverse-proxy.xml.in index 011e1b53c..e50e6e579 100644 --- a/interface-definitions/load-balancing_reverse-proxy.xml.in +++ b/interface-definitions/load-balancing_reverse-proxy.xml.in @@ -92,19 +92,6 @@                #include <include/generic-description.xml.i>                #include <include/haproxy/mode.xml.i>                #include <include/haproxy/http-response-headers.xml.i> -              <node name="parameters"> -                <properties> -                  <help>Backend parameters</help> -                </properties> -                <children> -                  <leafNode name="http-check"> -                    <properties> -                      <help>HTTP health check</help> -                      <valueless/> -                    </properties> -                  </leafNode> -                </children> -              </node>                <node name="http-check">                  <properties>                    <help>HTTP check configuration</help> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in index 8f9ae3fa6..927594c11 100644 --- a/interface-definitions/qos.xml.in +++ b/interface-definitions/qos.xml.in @@ -281,6 +281,7 @@                    #include <include/qos/mtu.xml.i>                    #include <include/qos/class-police-exceed.xml.i>                    #include <include/qos/class-match.xml.i> +                  #include <include/qos/class-match-group.xml.i>                    #include <include/qos/class-priority.xml.i>                    <leafNode name="priority">                      <defaultValue>20</defaultValue> @@ -415,6 +416,7 @@                    #include <include/qos/flows.xml.i>                    #include <include/qos/interval.xml.i>                    #include <include/qos/class-match.xml.i> +                  #include <include/qos/class-match-group.xml.i>                    #include <include/qos/queue-limit-1-4294967295.xml.i>                    #include <include/qos/queue-type.xml.i>                    <leafNode name="queue-type"> @@ -542,6 +544,8 @@                    #include <include/qos/flows.xml.i>                    #include <include/qos/interval.xml.i>                    #include <include/qos/class-match.xml.i> +                  #include <include/qos/class-match-group.xml.i> +                    <leafNode name="quantum">                      <properties>                        <help>Packet scheduling quantum</help> @@ -645,6 +649,7 @@                    #include <include/qos/flows.xml.i>                    #include <include/qos/interval.xml.i>                    #include <include/qos/class-match.xml.i> +                  #include <include/qos/class-match-group.xml.i>                    #include <include/qos/class-priority.xml.i>                    #include <include/qos/queue-average-packet.xml.i>                    #include <include/qos/queue-maximum-threshold.xml.i> @@ -767,6 +772,7 @@                      </children>                    </node>                    #include <include/qos/class-match.xml.i> +                  #include <include/qos/class-match-group.xml.i>                    <node name="realtime">                      <properties>                        <help>Realtime class settings</help> @@ -830,6 +836,39 @@            </tagNode>          </children>        </node> +      <tagNode name="traffic-match-group"> +        <properties> +          <help>Filter group for QoS policy</help> +          <valueHelp> +            <format>txt</format> +            <description>Match group name</description> +          </valueHelp> +          <constraint> +            <regex>[^-].*</regex> +          </constraint> +          <constraintErrorMessage>Match group name cannot start with hyphen</constraintErrorMessage> +        </properties> +          <children> +            #include <include/generic-description.xml.i> +            <tagNode name="match"> +              <properties> +                <help>Class matching rule name</help> +                <constraint> +                  <regex>[^-].*</regex> +                </constraint> +                <constraintErrorMessage>Match queue name cannot start with hyphen</constraintErrorMessage> +              </properties> +              <children> +                #include <include/generic-description.xml.i> +                #include <include/qos/class-match-ipv4.xml.i> +                #include <include/qos/class-match-ipv6.xml.i> +                #include <include/qos/class-match-mark.xml.i> +                #include <include/qos/class-match-vif.xml.i> +              </children> +            </tagNode> +            #include <include/qos/class-match-group.xml.i> +          </children> +      </tagNode>      </children>    </node>  </interfaceDefinition> diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in index 414c9a731..c7542f0d0 100644 --- a/interface-definitions/service_ipoe-server.xml.in +++ b/interface-definitions/service_ipoe-server.xml.in @@ -189,6 +189,7 @@            #include <include/accel-ppp/snmp.xml.i>            #include <include/generic-description.xml.i>            #include <include/name-server-ipv4-ipv6.xml.i> +          #include <include/accel-ppp/log.xml.i>          </children>        </node>      </children> diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in index 5d357c2f9..81228938f 100644 --- a/interface-definitions/service_pppoe-server.xml.in +++ b/interface-definitions/service_pppoe-server.xml.in @@ -153,6 +153,7 @@            #include <include/accel-ppp/wins-server.xml.i>            #include <include/generic-description.xml.i>            #include <include/name-server-ipv4-ipv6.xml.i> +          #include <include/accel-ppp/log.xml.i>          </children>        </node>      </children> diff --git a/interface-definitions/system_conntrack.xml.in b/interface-definitions/system_conntrack.xml.in index 219c6e28e..66f3d4e05 100644 --- a/interface-definitions/system_conntrack.xml.in +++ b/interface-definitions/system_conntrack.xml.in @@ -406,7 +406,7 @@                            <constraint>                              <validator name="numeric" argument="--range 1-999999"/>                            </constraint> -                          <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> +                          <constraintErrorMessage>Timeout rule number must be between 1 and 999999</constraintErrorMessage>                          </properties>                          <children>                            #include <include/generic-description.xml.i> @@ -421,7 +421,7 @@                            </node>                            <leafNode name="inbound-interface">                              <properties> -                              <help>Interface to ignore connections tracking on</help> +                              <help>Interface to apply custom connection timers on</help>                                <completionHelp>                                  <list>any</list>                                  <script>${vyos_completion_dir}/list_interfaces</script> @@ -464,7 +464,7 @@                            <constraint>                              <validator name="numeric" argument="--range 1-999999"/>                            </constraint> -                          <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> +                          <constraintErrorMessage>Timeout rule number must be between 1 and 999999</constraintErrorMessage>                          </properties>                          <children>                            #include <include/generic-description.xml.i> @@ -479,7 +479,7 @@                            </node>                            <leafNode name="inbound-interface">                              <properties> -                              <help>Interface to ignore connections tracking on</help> +                              <help>Interface to apply custom connection timers on</help>                                <completionHelp>                                  <list>any</list>                                  <script>${vyos_completion_dir}/list_interfaces</script> diff --git a/interface-definitions/vpn_l2tp.xml.in b/interface-definitions/vpn_l2tp.xml.in index 85a375db4..c00e82534 100644 --- a/interface-definitions/vpn_l2tp.xml.in +++ b/interface-definitions/vpn_l2tp.xml.in @@ -140,6 +140,7 @@                #include <include/accel-ppp/wins-server.xml.i>                #include <include/generic-description.xml.i>                #include <include/name-server-ipv4-ipv6.xml.i> +              #include <include/accel-ppp/log.xml.i>              </children>            </node>          </children> diff --git a/interface-definitions/vpn_pptp.xml.in b/interface-definitions/vpn_pptp.xml.in index a63633f57..8aec0cb1c 100644 --- a/interface-definitions/vpn_pptp.xml.in +++ b/interface-definitions/vpn_pptp.xml.in @@ -56,6 +56,7 @@                #include <include/accel-ppp/wins-server.xml.i>                #include <include/generic-description.xml.i>                #include <include/name-server-ipv4-ipv6.xml.i> +              #include <include/accel-ppp/log.xml.i>              </children>            </node>          </children> diff --git a/interface-definitions/vpn_sstp.xml.in b/interface-definitions/vpn_sstp.xml.in index d9ed1c040..5fd5c95ca 100644 --- a/interface-definitions/vpn_sstp.xml.in +++ b/interface-definitions/vpn_sstp.xml.in @@ -62,6 +62,7 @@                <constraintErrorMessage>Host-name must be alphanumeric and can contain hyphens</constraintErrorMessage>              </properties>            </leafNode> +          #include <include/accel-ppp/log.xml.i>          </children>        </node>      </children> diff --git a/interface-definitions/xml-component-version.xml.in b/interface-definitions/xml-component-version.xml.in index 10a1be242..67d86a1d0 100644 --- a/interface-definitions/xml-component-version.xml.in +++ b/interface-definitions/xml-component-version.xml.in @@ -48,4 +48,5 @@    #include <include/version/vyos-accel-ppp-version.xml.i>    #include <include/version/wanloadbalance-version.xml.i>    #include <include/version/webproxy-version.xml.i> +  #include <include/version/reverseproxy-version.xml.i>  </interfaceDefinition> diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py index ab723e707..212dc58ab 100644 --- a/smoketest/scripts/cli/base_accel_ppp_test.py +++ b/smoketest/scripts/cli/base_accel_ppp_test.py @@ -628,3 +628,21 @@ delegate={delegate_2_prefix},{delegate_mask},name={pool_name}"""              self.assertEqual(conf['connlimit']['limit'], limits)              self.assertEqual(conf['connlimit']['burst'], burst)              self.assertEqual(conf['connlimit']['timeout'], timeout) + +        def test_accel_log_level(self): +            self.basic_config() +            self.cli_commit() + +            # check default value +            conf = ConfigParser(allow_no_value=True) +            conf.read(self._config_file) +            self.assertEqual(conf['log']['level'], '3') + +            for log_level in range(0, 5): +                self.set(['log', 'level', str(log_level)]) +                self.cli_commit() +                # Validate configuration values +                conf = ConfigParser(allow_no_value=True) +                conf.read(self._config_file) + +                self.assertEqual(conf['log']['level'], str(log_level)) diff --git a/smoketest/scripts/cli/test_qos.py b/smoketest/scripts/cli/test_qos.py index 5977b2f41..b98c0e9b7 100755 --- a/smoketest/scripts/cli/test_qos.py +++ b/smoketest/scripts/cli/test_qos.py @@ -759,6 +759,101 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):          self.assertIn('filter parent ffff: protocol all pref 255 basic chain 0', tc_filters)          self.assertIn('action order 1:  police 0x2 rate 1Gbit burst 125000000b mtu 2Kb action drop overhead 0b', tc_filters) +    def test_15_traffic_match_group(self): +        interface = self._interfaces[0] +        self.cli_set(['qos', 'interface', interface, 'egress', 'VyOS-HTB']) +        base_policy_path = ['qos', 'policy', 'shaper', 'VyOS-HTB'] + +        #old syntax +        self.cli_set(base_policy_path + ['bandwidth', '100mbit']) +        self.cli_set(base_policy_path + ['class', '10', 'bandwidth', '40%']) +        self.cli_set(base_policy_path + ['class', '10', 'match', 'AF11', 'ip', 'dscp', 'AF11']) +        self.cli_set(base_policy_path + ['class', '10', 'match', 'AF41', 'ip', 'dscp', 'AF41']) +        self.cli_set(base_policy_path + ['class', '10', 'match', 'AF43', 'ip', 'dscp', 'AF43']) +        self.cli_set(base_policy_path + ['class', '10', 'match', 'CS4', 'ip', 'dscp', 'CS4']) +        self.cli_set(base_policy_path + ['class', '10', 'priority', '1']) +        self.cli_set(base_policy_path + ['class', '10', 'queue-type', 'fair-queue']) +        self.cli_set(base_policy_path + ['class', '20', 'bandwidth', '30%']) +        self.cli_set(base_policy_path + ['class', '20', 'match', 'EF', 'ip', 'dscp', 'EF']) +        self.cli_set(base_policy_path + ['class', '20', 'match', 'CS5', 'ip', 'dscp', 'CS5']) +        self.cli_set(base_policy_path + ['class', '20', 'priority', '2']) +        self.cli_set(base_policy_path + ['class', '20', 'queue-type', 'fair-queue']) +        self.cli_set(base_policy_path + ['default', 'bandwidth', '20%']) +        self.cli_set(base_policy_path + ['default', 'queue-type', 'fair-queue']) +        self.cli_commit() + +        tc_filters_old = cmd(f'tc -details filter show dev {interface}') +        self.assertIn('match 00280000/00ff0000', tc_filters_old) +        self.assertIn('match 00880000/00ff0000', tc_filters_old) +        self.assertIn('match 00980000/00ff0000', tc_filters_old) +        self.assertIn('match 00800000/00ff0000', tc_filters_old) +        self.assertIn('match 00a00000/00ff0000', tc_filters_old) +        self.assertIn('match 00b80000/00ff0000', tc_filters_old) +        # delete config by old syntax +        self.cli_delete(base_policy_path) +        self.cli_delete(['qos', 'interface', interface, 'egress', 'VyOS-HTB']) +        self.cli_commit() +        self.assertEqual('', cmd(f'tc -s filter show dev {interface}')) + +        self.cli_set(['qos', 'interface', interface, 'egress', 'VyOS-HTB']) +        # prepare traffic match group +        self.cli_set(['qos', 'traffic-match-group', 'VOICE', 'description', 'voice shaper']) +        self.cli_set(['qos', 'traffic-match-group', 'VOICE', 'match', 'EF', 'ip', 'dscp', 'EF']) +        self.cli_set(['qos', 'traffic-match-group', 'VOICE', 'match', 'CS5', 'ip', 'dscp', 'CS5']) + +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME_COMMON', 'description', 'real time common filters']) +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME_COMMON', 'match', 'AF43', 'ip', 'dscp', 'AF43']) +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME_COMMON', 'match', 'CS4', 'ip', 'dscp', 'CS4']) + +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME', 'description', 'real time shaper']) +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME', 'match', 'AF41', 'ip', 'dscp', 'AF41']) +        self.cli_set(['qos', 'traffic-match-group', 'REAL_TIME', 'match-group', 'REAL_TIME_COMMON']) + +        # new syntax +        self.cli_set(base_policy_path + ['bandwidth', '100mbit']) +        self.cli_set(base_policy_path + ['class', '10', 'bandwidth', '40%']) +        self.cli_set(base_policy_path + ['class', '10', 'match', 'AF11', 'ip', 'dscp', 'AF11']) +        self.cli_set(base_policy_path + ['class', '10', 'match-group', 'REAL_TIME']) +        self.cli_set(base_policy_path + ['class', '10', 'priority', '1']) +        self.cli_set(base_policy_path + ['class', '10', 'queue-type', 'fair-queue']) +        self.cli_set(base_policy_path + ['class', '20', 'bandwidth', '30%']) +        self.cli_set(base_policy_path + ['class', '20', 'match-group', 'VOICE']) +        self.cli_set(base_policy_path + ['class', '20', 'priority', '2']) +        self.cli_set(base_policy_path + ['class', '20', 'queue-type', 'fair-queue']) +        self.cli_set(base_policy_path + ['default', 'bandwidth', '20%']) +        self.cli_set(base_policy_path + ['default', 'queue-type', 'fair-queue']) +        self.cli_commit() + +        self.assertEqual(tc_filters_old, cmd(f'tc -details filter show dev {interface}')) + +    def test_16_wrong_traffic_match_group(self): +        interface = self._interfaces[0] +        self.cli_set(['qos', 'interface', interface]) + +        # Can not use both IPv6 and IPv4 in one match +        self.cli_set(['qos', 'traffic-match-group', '1', 'match', 'one', 'ip', 'dscp', 'EF']) +        self.cli_set(['qos', 'traffic-match-group', '1', 'match', 'one', 'ipv6', 'dscp', 'EF']) +        with self.assertRaises(ConfigSessionError) as e: +            self.cli_commit() + +        # check contain itself, should commit success +        self.cli_delete(['qos', 'traffic-match-group', '1', 'match', 'one', 'ipv6']) +        self.cli_set(['qos', 'traffic-match-group', '1', 'match-group', '1']) +        self.cli_commit() + +        # check cycle dependency, should commit success +        self.cli_set(['qos', 'traffic-match-group', '1', 'match-group', '3']) +        self.cli_set(['qos', 'traffic-match-group', '2', 'match', 'one', 'ip', 'dscp', 'CS4']) +        self.cli_set(['qos', 'traffic-match-group', '2', 'match-group', '1']) + +        self.cli_set(['qos', 'traffic-match-group', '3', 'match', 'one', 'ipv6', 'dscp', 'CS4']) +        self.cli_set(['qos', 'traffic-match-group', '3', 'match-group', '2']) +        self.cli_commit() + +        # inherit from non exist group, should commit success with warning +        self.cli_set(['qos', 'traffic-match-group', '3', 'match-group', 'unexpected']) +        self.cli_commit() +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/src/completion/qos/list_traffic_match_group.py b/src/completion/qos/list_traffic_match_group.py new file mode 100644 index 000000000..015d7ada9 --- /dev/null +++ b/src/completion/qos/list_traffic_match_group.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +from vyos.config import Config + + +def get_qos_traffic_match_group(): +    config = Config() +    base = ['qos', 'traffic-match-group'] +    conf = config.get_config_dict(base, key_mangling=('-', '_')) +    groups = [] + +    for group in conf.get('traffic_match_group', []): +        groups.append(group) + +    return groups + + +if __name__ == "__main__": +    groups = get_qos_traffic_match_group() +    print(" ".join(groups)) + diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py index 8a590cbc6..45248fb4a 100755 --- a/src/conf_mode/qos.py +++ b/src/conf_mode/qos.py @@ -17,6 +17,7 @@  from sys import exit  from netifaces import interfaces +from vyos.base import Warning  from vyos.config import Config  from vyos.configdep import set_dependents  from vyos.configdep import call_dependents @@ -89,6 +90,36 @@ def _clean_conf_dict(conf):          return conf +def _get_group_filters(config: dict, group_name: str, visited=None) -> dict: +    filters = dict() +    if not visited: +        visited = [group_name, ] +    else: +        if group_name in visited: +            return filters +        visited.append(group_name) + +    for filter, filter_config in config.get(group_name, {}).items(): +        if filter == 'match': +            for match, match_config in filter_config.items(): +               filters[f'{group_name}-{match}'] = match_config +        elif filter == 'match_group': +            for group in filter_config: +                filters.update(_get_group_filters(config, group, visited)) + +    return filters + + +def _get_group_match(config:dict, group_name:str) -> dict: +    match = dict() +    for key, val in _get_group_filters(config, group_name).items(): +        # delete duplicate matches +        if val not in match.values(): +            match[key] = val + +    return match + +  def get_config(config=None):      if config:          conf = config @@ -135,11 +166,27 @@ def get_config(config=None):      qos = conf.merge_defaults(qos, recursive=True) +    if 'traffic_match_group' in qos: +        for group, group_config in qos['traffic_match_group'].items(): +            if 'match_group' in group_config: +                qos['traffic_match_group'][group]['match'] = _get_group_match(qos['traffic_match_group'], group) +      for policy in qos.get('policy', []):          for p_name, p_config in qos['policy'][policy].items():              # cleanup empty match config              if 'class' in p_config:                  for cls, cls_config in p_config['class'].items(): +                    if 'match_group' in cls_config: +                        # merge group match to match +                        for group in cls_config['match_group']: +                            for match, match_conf in qos['traffic_match_group'].get(group, {'match': {}})['match'].items(): +                                if 'match' not in cls_config: +                                    cls_config['match'] = dict() +                                if match in cls_config['match']: +                                    cls_config['match'][f'{group}-{match}'] = match_conf +                                else: +                                    cls_config['match'][match] = match_conf +                      if 'match' in cls_config:                          cls_config['match'] = _clean_conf_dict(cls_config['match'])                          if cls_config['match'] == {}: @@ -147,6 +194,22 @@ def get_config(config=None):      return qos + +def _verify_match(cls_config: dict) -> None: +    if 'match' in cls_config: +        for match, match_config in cls_config['match'].items(): +            if {'ip', 'ipv6'} <= set(match_config): +                raise ConfigError( +                    f'Can not use both IPv6 and IPv4 in one match ({match})!') + + +def _verify_match_group_exist(cls_config, qos): +    if 'match_group' in cls_config: +        for group in cls_config['match_group']: +            if 'traffic_match_group' not in qos or group not in qos['traffic_match_group']: +                Warning(f'Match group "{group}" does not exist!') + +  def verify(qos):      if not qos or 'interface' not in qos:          return None @@ -174,11 +237,8 @@ def verify(qos):                          # bandwidth is not mandatory for priority-queue - that is why this is on the exception list                          if 'bandwidth' not in cls_config and policy_type not in ['priority_queue', 'round_robin', 'shaper_hfsc']:                              raise ConfigError(f'Bandwidth must be defined for policy "{policy}" class "{cls}"!') -                    if 'match' in cls_config: -                        for match, match_config in cls_config['match'].items(): -                            if {'ip', 'ipv6'} <= set(match_config): -                                 raise ConfigError(f'Can not use both IPv6 and IPv4 in one match ({match})!') - +                        _verify_match(cls_config) +                        _verify_match_group_exist(cls_config, qos)                  if policy_type in ['random_detect']:                      if 'precedence' in policy_config:                          for precedence, precedence_config in policy_config['precedence'].items(): @@ -216,8 +276,14 @@ def verify(qos):              if direction not in tmp:                  raise ConfigError(f'Selected QoS policy on interface "{interface}" only supports "{tmp}"!') +    if 'traffic_match_group' in qos: +        for group, group_config in qos['traffic_match_group'].items(): +            _verify_match(group_config) +            _verify_match_group_exist(group_config, qos) +      return None +  def generate(qos):      if not qos or 'interface' not in qos:          return None @@ -254,6 +320,7 @@ def apply(qos):      return None +  if __name__ == '__main__':      try:          c = get_config() diff --git a/src/migration-scripts/reverse-proxy/0-to-1 b/src/migration-scripts/reverse-proxy/0-to-1 new file mode 100755 index 000000000..d61493815 --- /dev/null +++ b/src/migration-scripts/reverse-proxy/0-to-1 @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +# T6409: Remove unused 'backend bk-example parameters' node + +from sys import argv, exit +from vyos.configtree import ConfigTree + +if len(argv) < 2: +    print("Must specify file name!") +    exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: +    config_file = f.read() + +config = ConfigTree(config_file) +base = ['load-balancing', 'reverse-proxy', 'backend'] +if not config.exists(base): +    # Nothing to do +    exit(0) + +# we need to run this for every configured network +for backend in config.list_nodes(base): +    param_node = base + [backend, 'parameters'] +    if config.exists(param_node): +        config.delete(param_node) + +try: +    with open(file_name, 'w') as f: +        f.write(config.to_string()) +except OSError as e: +    print("Failed to save the modified config: {}".format(e)) +    exit(1) diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py index 2b29f94bf..4ac4fb14a 100755 --- a/src/op_mode/ikev2_profile_generator.py +++ b/src/op_mode/ikev2_profile_generator.py @@ -144,15 +144,22 @@ tmp = reversed(tmp)  data['rfqdn'] = '.'.join(tmp)  pki = conf.get_config_dict(pki_base, get_first_key=True) -ca_name = data['authentication']['x509']['ca_certificate']  cert_name = data['authentication']['x509']['certificate'] -ca_cert = load_certificate(pki['ca'][ca_name]['certificate']) -cert = load_certificate(pki['certificate'][cert_name]['certificate']) +data['certs'] = [] + +for ca_name in data['authentication']['x509']['ca_certificate']: +    tmp = {} +    ca_cert = load_certificate(pki['ca'][ca_name]['certificate']) +    cert = load_certificate(pki['certificate'][cert_name]['certificate']) + + +    tmp['ca_cn'] = ca_cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value +    tmp['cert_cn'] = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value +    tmp['ca_cert'] = conf.value(pki_base + ['ca', ca_name, 'certificate']) + +    data['certs'].append(tmp) -data['ca_cn'] = ca_cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value -data['cert_cn'] = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value -data['ca_cert'] = conf.value(pki_base + ['ca', ca_name, 'certificate'])  esp_proposals = conf.get_config_dict(ipsec_base + ['esp-group', data['esp_group'], 'proposal'],                                       key_mangling=('-', '_'), get_first_key=True) diff --git a/src/op_mode/snmp_v3.py b/src/op_mode/snmp_v3.py index a1f76f0bc..abeb524dd 100755 --- a/src/op_mode/snmp_v3.py +++ b/src/op_mode/snmp_v3.py @@ -85,7 +85,7 @@ if __name__ == '__main__':          'user': [],          'view': []      } -     +      if c.exists_effective('service snmp v3 group'):          for g in c.list_effective_nodes('service snmp v3 group'):              group = { @@ -146,7 +146,6 @@ if __name__ == '__main__':              data['trap'].append(trap) -    print(data)      if args.all:           # Special case, print all templates !           tmpl = jinja2.Template(GROUP_OUTP_TMPL_SRC)  | 
