diff options
Diffstat (limited to 'data')
-rw-r--r-- | data/templates/dhcp-client/ipv6_new.tmpl | 47 | ||||
-rw-r--r-- | data/templates/macsec/wpa_supplicant.conf.tmpl | 21 | ||||
-rw-r--r-- | data/templates/ntp/ntp.conf.tmpl | 41 | ||||
-rw-r--r-- | data/templates/pppoe/ip-down.script.tmpl | 14 | ||||
-rw-r--r-- | data/templates/pppoe/ip-pre-up.script.tmpl | 8 | ||||
-rw-r--r-- | data/templates/pppoe/ip-up.script.tmpl | 12 | ||||
-rw-r--r-- | data/templates/pppoe/ipv6-up.script.tmpl | 24 | ||||
-rw-r--r-- | data/templates/pppoe/peer.tmpl | 29 | ||||
-rw-r--r-- | data/templates/wwan/ip-down.script.tmpl | 12 | ||||
-rw-r--r-- | data/templates/wwan/ip-pre-up.script.tmpl | 10 | ||||
-rw-r--r-- | data/templates/wwan/ip-up.script.tmpl | 12 | ||||
-rw-r--r-- | data/templates/wwan/peer.tmpl | 24 |
12 files changed, 157 insertions, 97 deletions
diff --git a/data/templates/dhcp-client/ipv6_new.tmpl b/data/templates/dhcp-client/ipv6_new.tmpl new file mode 100644 index 000000000..112431c5f --- /dev/null +++ b/data/templates/dhcp-client/ipv6_new.tmpl @@ -0,0 +1,47 @@ +# generated by dhcp.py +# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/ + +interface {{ ifname }} { + request domain-name-servers; + request domain-name; +{% if dhcpv6_options is defined %} +{% if dhcpv6_options.parameters_only is defined %} + information-only; +{% endif %} +{% if dhcpv6_options.temporary is not defined %} + send ia-na 1; # non-temporary address +{% endif %} +{% if dhcpv6_options.prefix_delegation is defined %} + send ia-pd 2; # prefix delegation +{% endif %} +{% endif %} +}; + +{% if dhcpv6_options is defined %} +{% if dhcpv6_options.temporary is not defined %} +id-assoc na 1 { + # Identity association NA +}; +{% endif %} + +{% if dhcpv6_options.prefix_delegation is defined %} +id-assoc pd 2 { +{% if dhcpv6_options.prefix_delegation.length is defined %} + prefix ::/{{ dhcpv6_options.prefix_delegation.length }} infinity; +{% endif %} +{% for interface in dhcpv6_options.prefix_delegation.interface %} + prefix-interface {{ interface }} { +{% if dhcpv6_options.prefix_delegation.interface[interface].sla_id is defined %} + sla-id {{ dhcpv6_options.prefix_delegation.interface[interface].sla_id }}; +{% endif %} +{% if dhcpv6_options.prefix_delegation.interface[interface].sla_len is defined %} + sla-len {{ dhcpv6_options.prefix_delegation.interface[interface].sla_len }}; +{% endif %} +{% if dhcpv6_options.prefix_delegation.interface[interface].address is defined %} + ifid {{ dhcpv6_options.prefix_delegation.interface[interface].address }}; +{% endif %} + }; +{% endfor %} +}; +{% endif %} +{% endif %} diff --git a/data/templates/macsec/wpa_supplicant.conf.tmpl b/data/templates/macsec/wpa_supplicant.conf.tmpl index a614d23f5..1731bf160 100644 --- a/data/templates/macsec/wpa_supplicant.conf.tmpl +++ b/data/templates/macsec/wpa_supplicant.conf.tmpl @@ -45,9 +45,10 @@ network={ # - the key server has decided to enable MACsec # 0: Encrypt traffic (default) # 1: Integrity only - macsec_integ_only={{ '0' if security_encrypt else '1' }} + macsec_integ_only={{ '0' if security is defined and security.encrypt is defined else '1' }} -{% if security_encrypt %} +{% if security is defined %} +{% if security.encrypt is defined %} # mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair. # In this mode, instances of wpa_supplicant can act as MACsec peers. The peer @@ -56,21 +57,22 @@ network={ # hex-string (32 hex-digits) or a 32-byte (256-bit) hex-string (64 hex-digits) # mka_ckn (CKN = CAK Name) takes a 1..32-bytes (8..256 bit) hex-string # (2..64 hex-digits) - mka_cak={{ security_mka_cak }} - mka_ckn={{ security_mka_ckn }} + mka_cak={{ security.mka.cak }} + mka_ckn={{ security.mka.ckn }} # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being # default priority - mka_priority={{ security_mka_priority }} -{% endif %} -{% if security_replay_window %} + mka_priority={{ security.mka.priority }} +{% endif %} + +{% if security.replay_window is defined %} # macsec_replay_protect: IEEE 802.1X/MACsec replay protection # This setting applies only when MACsec is in use, i.e., # - macsec_policy is enabled # - the key server has decided to enable MACsec # 0: Replay protection disabled (default) # 1: Replay protection enabled - macsec_replay_protect={{ '1' if security_replay_window else '0' }} + macsec_replay_protect=1 # macsec_replay_window: IEEE 802.1X/MACsec replay protection window # This determines a window in which replay is tolerated, to allow receipt @@ -80,7 +82,8 @@ network={ # - the key server has decided to enable MACsec # 0: No replay window, strict check (default) # 1..2^32-1: number of packets that could be misordered - macsec_replay_window={{ security_replay_window }} + macsec_replay_window={{ security.replay_window }} +{% endif %} {% endif %} } diff --git a/data/templates/ntp/ntp.conf.tmpl b/data/templates/ntp/ntp.conf.tmpl index 52042d218..1c51929fd 100644 --- a/data/templates/ntp/ntp.conf.tmpl +++ b/data/templates/ntp/ntp.conf.tmpl @@ -13,26 +13,35 @@ restrict -6 ::1 # # Configurable section # - -{% if servers -%} -{% for s in servers -%} -# Server configuration for: {{ s.name }} -server {{ s.name }} iburst {{ s.options | join(" ") }} -{% endfor -%} +{% if server %} +{% for srv in server %} +{% set options = '' %} +{% set options = options + 'noselect ' if server[srv].noselect is defined else '' %} +{% set options = options + 'preempt ' if server[srv].preempt is defined else '' %} +{% set options = options + 'prefer ' if server[srv].prefer is defined else '' %} +server {{ srv }} iburst {{ options }} +{% endfor %} {% endif %} -{% if allowed_networks -%} -{% for n in allowed_networks -%} -# Client configuration for network: {{ n.network }} -restrict {{ n.address }} mask {{ n.netmask }} nomodify notrap nopeer - -{% endfor -%} +{% if allow_clients is defined and allow_clients.address is defined %} +# Allowed clients configuration +{% if allow_clients.address is string %} +restrict {{ allow_clients.address|address_from_cidr }} mask {{ allow_clients.address|netmask_from_cidr }} nomodify notrap nopeer +{% else %} +{% for address in allow_clients.address %} +restrict {{ address|address_from_cidr }} mask {{ address|netmask_from_cidr }} nomodify notrap nopeer +{% endfor %} +{% endif %} {% endif %} -{% if listen_address -%} +{% if listen_address %} # NTP should listen on configured addresses only interface ignore wildcard -{% for a in listen_address -%} -interface listen {{ a }} -{% endfor -%} +{% if listen_address is string %} +interface listen {{ listen_address }} +{% else %} +{% for address in listen_address %} +interface listen {{ address }} +{% endfor %} +{% endif %} {% endif %} diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl index 9e6bd2a8e..f69f9fc1a 100644 --- a/data/templates/pppoe/ip-down.script.tmpl +++ b/data/templates/pppoe/ip-down.script.tmpl @@ -2,21 +2,21 @@ # As PPPoE is an "on demand" interface we need to re-configure it when it # becomes up -if [ "$6" != "{{ intf }}" ]; then +if [ "$6" != "{{ ifname }}" ]; then exit fi # add some info to syslog -DIALER_PID=$(cat /var/run/{{ intf }}.pid) +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" {% if not on_demand %} # See https://phabricator.vyos.net/T2248. Determine if we are enslaved to a # VRF, this is needed to properly insert the default route. VRF_NAME="" -if [ -d /sys/class/net/{{ intf }}/upper_* ]; then +if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) # Remove upper_ prefix from result string VRF=${VRF#"upper_"} # Populate variable to run in VR context @@ -24,13 +24,13 @@ if [ -d /sys/class/net/{{ intf }}/upper_* ]; then fi # Always delete default route when interface goes down -vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME}" +vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ ifname }} ${VRF_NAME}" {% if ipv6_enable %} -vtysh -c "conf t" ${VRF_NAME} -c "no ipv6 route ::/0 {{ intf }} ${VRF_NAME}" +vtysh -c "conf t" ${VRF_NAME} -c "no ipv6 route ::/0 {{ ifname }} ${VRF_NAME}" {% endif %} {% endif %} {% if dhcpv6_pd_interfaces %} # Start wide dhcpv6 client -systemctl stop dhcp6c@{{ intf }}.service +systemctl stop dhcp6c@{{ ifname }}.service {% endif %} diff --git a/data/templates/pppoe/ip-pre-up.script.tmpl b/data/templates/pppoe/ip-pre-up.script.tmpl index 6a2d2af94..cf85ed067 100644 --- a/data/templates/pppoe/ip-pre-up.script.tmpl +++ b/data/templates/pppoe/ip-pre-up.script.tmpl @@ -2,17 +2,17 @@ # As PPPoE is an "on demand" interface we need to re-configure it when it # becomes up -if [ "$6" != "{{ intf }}" ]; then +if [ "$6" != "{{ ifname }}" ]; then exit fi # add some info to syslog -DIALER_PID=$(cat /var/run/{{ intf }}.pid) +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" -echo "{{ description }}" > /sys/class/net/{{ intf }}/ifalias +echo "{{ description }}" > /sys/class/net/{{ ifname }}/ifalias {% if vrf -%} logger -t pppd[$DIALER_PID] "configuring dialer interface $6 for VRF {{ vrf }}" -ip link set dev {{ intf }} master {{ vrf }} +ip link set dev {{ ifname }} master {{ vrf }} {% endif %} diff --git a/data/templates/pppoe/ip-up.script.tmpl b/data/templates/pppoe/ip-up.script.tmpl index a274296b6..6adea4bd7 100644 --- a/data/templates/pppoe/ip-up.script.tmpl +++ b/data/templates/pppoe/ip-up.script.tmpl @@ -2,13 +2,13 @@ # As PPPoE is an "on demand" interface we need to re-configure it when it # becomes up -if [ "$6" != "{{ intf }}" ]; then +if [ "$6" != "{{ ifname }}" ]; then exit fi {% if not on_demand %} # add some info to syslog -DIALER_PID=$(cat /var/run/{{ intf }}.pid) +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" {% if default_route != 'none' -%} @@ -17,9 +17,9 @@ logger -t pppd[$DIALER_PID] "executing $0" SED_OPT="^ip route" VRF_NAME="" -if [ -d /sys/class/net/{{ intf }}/upper_* ]; then +if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) # Remove upper_ prefix from result string VRF=${VRF#"upper_"} # generate new SED command @@ -43,7 +43,7 @@ done {% endif %} # Add default route to default or VRF routing table -vtysh -c "conf t" ${VTY_OPT} -c "ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME}" -logger -t pppd[$DIALER_PID] "added default route via {{ intf }} ${VRF_NAME}" +vtysh -c "conf t" ${VTY_OPT} -c "ip route 0.0.0.0/0 {{ ifname }} ${VRF_NAME}" +logger -t pppd[$DIALER_PID] "added default route via {{ ifname }} ${VRF_NAME}" {% endif %} {% endif %} diff --git a/data/templates/pppoe/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl index 097f1d4c3..511e288ea 100644 --- a/data/templates/pppoe/ipv6-up.script.tmpl +++ b/data/templates/pppoe/ipv6-up.script.tmpl @@ -3,17 +3,15 @@ # As PPPoE is an "on demand" interface we need to re-configure it when it # becomes up -if [ "$6" != "{{ intf }}" ]; then +if [ "$6" != "{{ ifname }}" ]; then exit fi -set -x - {% if ipv6_autoconf -%} # add some info to syslog -DIALER_PID=$(cat /var/run/{{ intf }}.pid) +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" -logger -t pppd[$DIALER_PID] "configuring interface {{ intf }} via {{ source_interface }}" +logger -t pppd[$DIALER_PID] "configuring interface {{ ifname }} via {{ source_interface }}" # Configure interface-specific Host/Router behaviour. # Note: It is recommended to have the same setting on all interfaces; mixed @@ -22,7 +20,7 @@ logger -t pppd[$DIALER_PID] "configuring interface {{ intf }} via {{ source_inte # 0 Forwarding disabled # 1 Forwarding enabled # -echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/forwarding +echo 1 > /proc/sys/net/ipv6/conf/{{ ifname }}/forwarding # Accept Router Advertisements; autoconfigure using them. # @@ -36,15 +34,15 @@ echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/forwarding # 2 Overrule forwarding behaviour. Accept Router Advertisements # even if forwarding is enabled. # -echo 2 > /proc/sys/net/ipv6/conf/{{ intf }}/accept_ra +echo 2 > /proc/sys/net/ipv6/conf/{{ ifname }}/accept_ra # Autoconfigure addresses using Prefix Information in Router Advertisements. -echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/autoconf +echo 1 > /proc/sys/net/ipv6/conf/{{ ifname }}/autoconf {% endif %} {% if dhcpv6_pd_interfaces %} # Start wide dhcpv6 client -systemctl start dhcp6c@{{ intf }}.service +systemctl start dhcp6c@{{ ifname }}.service {% endif %} @@ -54,9 +52,9 @@ systemctl start dhcp6c@{{ intf }}.service SED_OPT="^ipv6 route" VRF_NAME="" -if [ -d /sys/class/net/{{ intf }}/upper_* ]; then +if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) # Remove upper_ prefix from result string VRF=${VRF#"upper_"} # generate new SED command @@ -80,8 +78,8 @@ done {% endif %} # Add default route to default or VRF routing table -vtysh -c "conf t" ${VTY_OPT} -c "ipv6 route ::/0 {{ intf }} ${VRF_NAME}" -logger -t pppd[$DIALER_PID] "added default route via {{ intf }} ${VRF_NAME}" +vtysh -c "conf t" ${VTY_OPT} -c "ipv6 route ::/0 {{ ifname }} ${VRF_NAME}" +logger -t pppd[$DIALER_PID] "added default route via {{ ifname }} ${VRF_NAME}" {% endif %} diff --git a/data/templates/pppoe/peer.tmpl b/data/templates/pppoe/peer.tmpl index fb85265b2..e909843a5 100644 --- a/data/templates/pppoe/peer.tmpl +++ b/data/templates/pppoe/peer.tmpl @@ -40,32 +40,37 @@ maxfail 0 plugin rp-pppoe.so {{ source_interface }} persist -ifname {{ intf }} -ipparam {{ intf }} +ifname {{ ifname }} +ipparam {{ ifname }} debug mtu {{ mtu }} mru {{ mtu }} -user "{{ auth_username }}" -password "{{ auth_password }}" -{% if name_server -%} -usepeerdns + +{% if authentication is defined %} +{{ "user " + authentication.user if authentication.user is defined }} +{{ "password " + authentication.password if authentication.password is defined }} {% endif %} -{% if ipv6_enable -%} + +{{ "usepeerdns" if no_peer_dns is not defined }} + +{% if ipv6 is defined and ipv6.enable is defined -%} +ipv6 ipv6cp-use-ipaddr {% endif %} -{% if service_name -%} + +{% if service_name is defined -%} rp_pppoe_service "{{ service_name }}" {% endif %} -{% if on_demand %} + +{% if connect_on_demand is defined %} demand # See T2249. PPP default route options should only be set when in on-demand # mode. As soon as we are not in on-demand mode the default-route handling is # passed to the ip-up.d/ip-down.s scripts which is required for VRF support. -{% if 'auto' in default_route -%} +{% if 'auto' in default_route -%} defaultroute -{% elif 'force' in default_route -%} +{% elif 'force' in default_route -%} defaultroute replacedefaultroute -{% endif %} +{% endif %} {% endif %} diff --git a/data/templates/wwan/ip-down.script.tmpl b/data/templates/wwan/ip-down.script.tmpl index f7b38cbc5..9dc15ea99 100644 --- a/data/templates/wwan/ip-down.script.tmpl +++ b/data/templates/wwan/ip-down.script.tmpl @@ -11,17 +11,17 @@ fi # Determine if we are running inside a VRF or not, required for proper routing table # NOTE: the down script can not be properly templated as we need the VRF name, # which is not present on deletion, thus we read it from the operating system. -if [ -d /sys/class/net/{{ intf }}/upper_* ]; then +if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) # Remove upper_ prefix from result string VRF_NAME=${VRF#"upper_"} # Remove default route from VRF routing table - vtysh -c "conf t" -c "vrf ${VRF_NAME}" -c "no ip route 0.0.0.0/0 {{ intf }}" + vtysh -c "conf t" -c "vrf ${VRF_NAME}" -c "no ip route 0.0.0.0/0 {{ ifname }}" else # Remove default route from GRT (global routing table) - vtysh -c "conf t" -c "no ip route 0.0.0.0/0 {{ intf }}" + vtysh -c "conf t" -c "no ip route 0.0.0.0/0 {{ ifname }}" fi -DIALER_PID=$(cat /var/run/{{ intf }}.pid) -logger -t pppd[$DIALER_PID] "removed default route via {{ intf }} metric {{ metric }}" +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) +logger -t pppd[$DIALER_PID] "removed default route via {{ ifname }} metric {{ backup.distance }}" diff --git a/data/templates/wwan/ip-pre-up.script.tmpl b/data/templates/wwan/ip-pre-up.script.tmpl index 7a17a1c71..efc065bad 100644 --- a/data/templates/wwan/ip-pre-up.script.tmpl +++ b/data/templates/wwan/ip-pre-up.script.tmpl @@ -7,17 +7,17 @@ ipparam=$6 # device name and metric are received using ipparam device=`echo "$ipparam"|awk '{ print $1 }'` -if [ "$device" != "{{ intf }}" ]; then +if [ "$device" != "{{ ifname }}" ]; then exit fi # add some info to syslog -DIALER_PID=$(cat /var/run/{{ intf }}.pid) +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) logger -t pppd[$DIALER_PID] "executing $0" -echo "{{ description }}" > /sys/class/net/{{ intf }}/ifalias +echo "{{ description }}" > /sys/class/net/{{ ifname }}/ifalias {% if vrf -%} -logger -t pppd[$DIALER_PID] "configuring interface {{ intf }} for VRF {{ vrf }}" -ip link set dev {{ intf }} master {{ vrf }} +logger -t pppd[$DIALER_PID] "configuring interface {{ ifname }} for VRF {{ vrf }}" +ip link set dev {{ ifname }} master {{ vrf }} {% endif %} diff --git a/data/templates/wwan/ip-up.script.tmpl b/data/templates/wwan/ip-up.script.tmpl index 3a7eec800..2603a0286 100644 --- a/data/templates/wwan/ip-up.script.tmpl +++ b/data/templates/wwan/ip-up.script.tmpl @@ -9,17 +9,17 @@ if [ -z $(echo $2 | egrep "(ttyS[0-9]+|usb[0-9]+b.*)$") ]; then fi # Determine if we are running inside a VRF or not, required for proper routing table -if [ -d /sys/class/net/{{ intf }}/upper_* ]; then +if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) # Remove upper_ prefix from result string VRF_NAME=${VRF#"upper_"} # Remove default route from VRF routing table - vtysh -c "conf t" -c "vrf ${VRF_NAME}" -c "ip route 0.0.0.0/0 {{ intf }} {{ metric }}" + vtysh -c "conf t" -c "vrf ${VRF_NAME}" -c "ip route 0.0.0.0/0 {{ ifname }} {{ backup.distance }}" else # Remove default route from GRT (global routing table) - vtysh -c "conf t" -c "ip route 0.0.0.0/0 {{ intf }} {{ metric }}" + vtysh -c "conf t" -c "ip route 0.0.0.0/0 {{ ifname }} {{ backup.distance }}" fi -DIALER_PID=$(cat /var/run/{{ intf }}.pid) -logger -t pppd[$DIALER_PID] "added default route via {{ intf }} metric {{ metric }} ${VRF_NAME}" +DIALER_PID=$(cat /var/run/{{ ifname }}.pid) +logger -t pppd[$DIALER_PID] "added default route via {{ ifname }} metric {{ backup.distance }} ${VRF_NAME}" diff --git a/data/templates/wwan/peer.tmpl b/data/templates/wwan/peer.tmpl index 0168283fd..aa759f741 100644 --- a/data/templates/wwan/peer.tmpl +++ b/data/templates/wwan/peer.tmpl @@ -1,19 +1,18 @@ ### Autogenerated by interfaces-wirelessmodem.py ### -{% if description %} -# {{ description }} -{% endif %} -ifname {{ intf }} -ipparam {{ intf }} -linkname {{ intf }} -{% if name_server -%} -usepeerdns -{%- endif %} +{{ "# description: " + description if description is defined }} +ifname {{ ifname }} +ipparam {{ ifname }} +linkname {{ ifname }} +{{ "usepeerdns" if no_peer_dns is defined }} # physical device {{ device }} lcp-echo-failure 0 115200 debug +debug +mtu {{ mtu }} +mru {{ mtu }} nodefaultroute ipcp-max-failure 4 ipcp-accept-local @@ -22,8 +21,7 @@ noauth crtscts lock persist -{% if on_demand -%} -demand -{%- endif %} +{{ "demand" if ondemand is defined }} + +connect '/usr/sbin/chat -v -t6 -f /etc/ppp/peers/chat.{{ ifname }}' -connect '/usr/sbin/chat -v -t6 -f {{ chat_script }}' |