Changeset 41281


Ignore:
Timestamp:
2014-06-19T18:06:44+02:00 (4 years ago)
Author:
jow
Message:

base-files: depend on jsonfilter and rewrite network.sh to use it

Switches /lib/functions/network.sh from jshn based json parsing to
jsonfilter expression while keeping the existing api.

Expensive methods like "network_find_wan" are up to 20x faster now.

Signed-off-by: Jo-Philipp Wich <jow@…>

Location:
trunk/package/base-files
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/base-files/Makefile

    r40906 r41281  
    11# 
    2 # Copyright (C) 2007-2013 OpenWrt.org 
     2# Copyright (C) 2007-2014 OpenWrt.org 
    33# Copyright (C) 2010 Vertical Communications 
    44# 
     
    1212 
    1313PKG_NAME:=base-files 
    14 PKG_RELEASE:=153 
     14PKG_RELEASE:=154 
    1515 
    1616PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/ 
     
    2929  SECTION:=base 
    3030  CATEGORY:=Base system 
    31   DEPENDS:=+netifd +libc +procd 
     31  DEPENDS:=+netifd +libc +procd +jsonfilter 
    3232  TITLE:=Base filesystem for OpenWrt 
    3333  URL:=http://openwrt.org/ 
  • trunk/package/base-files/files/lib/functions/network.sh

    r39099 r41281  
    1 . /usr/share/libubox/jshn.sh 
    2  
    3 __network_set_cache() 
    4 { 
    5         if [ -n "$3" ]; then 
    6                 eval "export -- __NETWORK_CV_$1='$3'" 
    7                 __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1" 
    8         elif json_get_var "__NETWORK_CV_$1" "$2"; then 
    9                 __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1" 
     1# 1: destination variable 
     2# 2: interface 
     3# 3: path 
     4# 4: separator 
     5# 5: limit 
     6__network_ifstatus() { 
     7        local __tmp 
     8 
     9        [ -z "$__NETWORK_CACHE" ] && \ 
     10                export __NETWORK_CACHE="$(ubus call network.interface dump)" 
     11 
     12        __tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "$__NETWORK_CACHE" -e "$1=@.interface${2:+[@.interface='$2']}$3")" 
     13 
     14        [ -z "$__tmp" ] && \ 
     15                unset "$1" && \ 
     16                return 1 
     17 
     18        eval "$__tmp" 
     19} 
     20 
     21# determine first IPv4 address of given logical interface 
     22# 1: destination variable 
     23# 2: interface 
     24network_get_ipaddr() { 
     25        __network_ifstatus "$1" "$2" "['ipv4-address'][0].address"; 
     26} 
     27 
     28# determine first IPv6 address of given logical interface 
     29# 1: destination variable 
     30# 2: interface 
     31network_get_ipaddr6() { 
     32        __network_ifstatus "$1" "$2" "['ipv6-address'][0].address"; 
     33} 
     34 
     35# determine first IPv4 subnet of given logical interface 
     36# 1: destination variable 
     37# 2: interface 
     38network_get_subnet() { 
     39        __network_ifstatus "$1" "$2" "['ipv4-address'][0]['address','mask']" "/" 
     40} 
     41 
     42# determine first IPv6 subnet of given logical interface 
     43# 1: destination variable 
     44# 2: interface 
     45network_get_subnet6() { 
     46        __network_ifstatus "$1" "$2" "['ipv6-address'][0]['address','mask']" "/" 
     47} 
     48 
     49# determine first IPv6 prefix of given logical interface 
     50# 1: destination variable 
     51# 2: interface 
     52network_get_prefix6() { 
     53        __network_ifstatus "$1" "$2" "['ipv6-prefix'][0]['address','mask']" "/" 
     54} 
     55 
     56# determine all IPv4 addresses of given logical interface 
     57# 1: destination variable 
     58# 2: interface 
     59network_get_ipaddrs() { 
     60        __network_ifstatus "$1" "$2" "['ipv4-address'][*].address" 
     61} 
     62 
     63# determine all IPv6 addresses of given logical interface 
     64# 1: destination variable 
     65# 2: interface 
     66network_get_ipaddrs6() { 
     67        local __addr 
     68        local __list="" 
     69 
     70        if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*].address"; then 
     71                for __addr in $__addr; do 
     72                        case "$__addr" in 
     73                                *:)     __list="${__list:+$__list }${__addr}1" ;; 
     74                                *)  __list="${__list:+$__list }${__addr}"  ;; 
     75                        esac 
     76                done 
     77 
     78                export "$1=$__list" 
     79                return 0 
    1080        fi 
    11 } 
    12  
    13 __network_export() 
    14 { 
    15         local __v="__NETWORK_CV_$2" 
    16         eval "export -- \"$1=\${$__v:+\${$__v$4}$3}\"; [ -n \"\${$__v+x}\" ]" 
    17 } 
    18  
    19 __network_parse_ifstatus() 
    20 { 
    21         local __iface="$1" 
    22         local __key="${__iface}" 
    23         local __tmp 
    24         local __idx 
    25         local __list 
    26         local __old_ns 
    27  
    28         case "$__iface" in 
    29                 *[^a-zA-Z0-9_]*) return 1 ;; 
    30         esac 
    31  
    32         __network_export __tmp "${__key}__parsed" && return 0 
    33         __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" 
    34         [ -n "$__tmp" ] || return 1 
    35  
    36         json_set_namespace "network" __old_ns 
    37         json_load "$__tmp" 
    38  
    39         __network_set_cache "${__key}__parsed" "" "1" 
    40  
    41         for __tmp in "" "_inactive"; do 
    42  
    43                 __key="${__key}${__tmp}" 
    44  
    45                 # parse addresses 
    46                 local __family 
    47                 for __family in 4 6; do 
    48  
    49                         __list="" 
    50  
    51                         if json_is_a "ipv${__family}_address" array; then 
    52  
    53                                 json_select "ipv${__family}_address" 
    54  
    55                                 __idx=1 
    56  
    57                                 while json_is_a "$__idx" object; do 
    58  
    59                                         json_select "$((__idx++))" 
    60                                         json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp" 
    61                                         json_get_var __tmp "mask"    && __list="${__list:+$__list/}$__tmp" 
    62                                         json_select ".." 
    63  
    64                                 done 
    65  
    66                                 json_select ".." 
    67  
    68                         fi 
    69  
    70                         if json_is_a "ipv${__family}_prefix_assignment" array; then 
    71  
    72                                 json_select "ipv${__family}_prefix_assignment" 
    73  
    74                                 __idx=1 
    75  
    76                                 while json_is_a "$__idx" object; do 
    77  
    78                                         json_select "$((__idx++))" 
    79                                         json_get_var __tmp "address" && __list="${__list:+$__list }${__tmp}1" 
    80                                         json_get_var __tmp "mask"    && __list="${__list:+$__list/}$__tmp" 
    81                                         json_select ".." 
    82  
    83                                 done 
    84  
    85                                 json_select ".." 
    86  
    87                         fi 
    88  
    89                         if [ -n "$__list" ]; then 
    90                                 __network_set_cache "${__key}_address${__family}" "" "$__list" 
    91                         fi 
    92  
     81 
     82        unset "$1" 
     83        return 1 
     84} 
     85 
     86# determine all IPv4 subnets of given logical interface 
     87# 1: destination variable 
     88# 2: interface 
     89network_get_subnets() { 
     90        __network_ifstatus "$1" "$2" "['ipv4-address'][*]['address','mask']" "/ " 
     91} 
     92 
     93# determine all IPv6 subnets of given logical interface 
     94# 1: destination variable 
     95# 2: interface 
     96network_get_subnets6() { 
     97        local __addr 
     98        local __list="" 
     99 
     100        if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*]['address','mask']" "/ "; then 
     101                for __addr in $__addr; do 
     102                        case "$__addr" in 
     103                                *:/*) __list="${__list:+$__list }${__addr%/*}1/${__addr##*/}" ;; 
     104                                *)    __list="${__list:+$__list }${__addr}"                   ;; 
     105                        esac 
    93106                done 
    94107 
    95                 # parse prefixes 
    96                 if json_is_a "ipv6_prefix" array; then 
    97                         json_select "ipv6_prefix" 
    98  
    99                         __idx=1 
    100                         __list="" 
    101  
    102                         while json_is_a "$__idx" object; do 
    103  
    104                                 json_select "$((__idx++))" 
    105                                 json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp" 
    106                                 json_get_var __tmp "mask"    && __list="${__list:+$__list/}$__tmp" 
    107                                 json_select ".." 
    108  
    109                         done 
    110  
    111                         json_select ".." 
    112  
    113  
    114                         if [ -n "$__list" ]; then 
    115                                 __network_set_cache "${__key}_prefix6" "" "$__list" 
    116                         fi 
    117  
    118                 fi 
    119  
    120                 # parse routes 
    121                 if json_is_a route array; then 
    122  
    123                         json_select "route" 
    124  
    125                         local __idx=1 
    126                         while json_is_a "$__idx" object; do 
    127  
    128                                 json_select "$((__idx++))" 
    129                                 json_get_var __tmp table 
    130  
    131                                 if [ -z "$__tmp" ]; then 
    132                                         json_get_var __tmp target 
    133  
    134                                         case "${__tmp}" in 
    135                                                 0.0.0.0) 
    136                                                         __network_set_cache "${__key}_gateway4" nexthop 
    137                                                 ;; 
    138                                                 ::) 
    139                                                         __network_set_cache "${__key}_gateway6" nexthop 
    140                                                 ;; 
    141                                         esac 
    142                                 fi 
    143  
    144                                 json_select ".." 
    145  
    146                         done 
    147  
    148                         json_select ".." 
    149  
    150                 fi 
    151  
    152                 # parse dns info 
    153                 local __field 
    154                 for __field in "dns_server" "dns_search"; do 
    155                         if json_is_a "$__field" array; then 
    156  
    157                                 json_select "$__field" 
    158  
    159                                 __idx=1 
    160                                 __list="" 
    161  
    162                                 while json_is_a "$__idx" string; do 
    163  
    164                                         json_get_var __tmp "$((__idx++))" 
    165                                         __list="${__list:+$__list }$__tmp" 
    166  
    167                                 done 
    168  
    169                                 json_select ".." 
    170  
    171                                 if [ -n "$__list" ]; then 
    172                                         __network_set_cache "${__key}_${__field}" "" "$__list" 
    173                                 fi 
    174                         fi 
    175                 done 
    176  
    177                 # parse up state, proto, device and physdev 
    178                 for __field in "up" "proto" "l3_device" "device"; do 
    179                         if json_get_type __tmp "$__field"; then 
    180                                 __network_set_cache "${__key}_${__field}" "$__field" 
    181                         fi 
    182                 done 
    183  
    184                 # descend into inactive table 
    185                 json_is_a "inactive" object && json_select "inactive" 
    186  
    187         done 
    188  
    189         json_cleanup 
    190         json_set_namespace "$__old_ns" 
    191  
    192         return 0 
    193 } 
    194  
    195  
    196 __network_ipaddr() 
    197 { 
    198         local __var="$1" 
    199         local __iface="$2" 
    200         local __field="$3" 
    201         local __subst="$4" 
    202         local __list="$5" 
    203         local __tmp="" 
    204  
    205         __network_parse_ifstatus "$__iface" || return 1 
    206  
    207         if [ $__list = 1 ] && [ -n "$__subst" ]; then 
    208                 __network_export "__list" "${__iface}_${__field}" 
    209  
    210                 for __list in $__list; do 
    211                         eval "__tmp=\"${__tmp:+$__tmp }\${__list$__subst}\"" 
    212                 done 
    213  
    214                 export -- "$__var=$__tmp"; [ -n "$__tmp" ] 
    215                 return $? 
     108                export "$1=$__list" 
     109                return 0 
    216110        fi 
    217111 
    218         __network_export "$__var" "${__iface}_${__field}" "" "$__subst" 
    219         return $? 
    220 } 
    221  
    222 # determine first IPv4 address of given logical interface 
    223 # 1: destination variable 
    224 # 2: interface 
    225 network_get_ipaddr() { __network_ipaddr "$1" "$2" "address4" "%%/*" 0; } 
    226  
    227 # determine first IPv6 address of given logical interface 
    228 # 1: destination variable 
    229 # 2: interface 
    230 network_get_ipaddr6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 0; } 
    231  
    232 # determine first IPv4 subnet of given logical interface 
    233 # 1: destination variable 
    234 # 2: interface 
    235 network_get_subnet() { __network_ipaddr "$1" "$2" "address4" "%% *" 0; } 
    236  
    237 # determine first IPv6 subnet of given logical interface 
    238 # 1: destination variable 
    239 # 2: interface 
    240 network_get_subnet6() { __network_ipaddr "$1" "$2" "address6" "%% *" 0; } 
    241  
    242 # determine first IPv6 prefix of given logical interface 
    243 # 1: destination variable 
    244 # 2: interface 
    245 network_get_prefix6() { __network_ipaddr "$1" "$2" "prefix6" "%% *" 0; } 
    246  
    247 # determine all IPv4 addresses of given logical interface 
    248 # 1: destination variable 
    249 # 2: interface 
    250 network_get_ipaddrs() { __network_ipaddr "$1" "$2" "address4" "%%/*" 1; } 
    251  
    252 # determine all IPv6 addresses of given logical interface 
    253 # 1: destination variable 
    254 # 2: interface 
    255 network_get_ipaddrs6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 1; } 
    256  
    257 # determine all IPv4 subnets of given logical interface 
    258 # 1: destination variable 
    259 # 2: interface 
    260 network_get_subnets() { __network_ipaddr "$1" "$2" "address4" "" 1; } 
    261  
    262 # determine all IPv6 subnets of given logical interface 
    263 # 1: destination variable 
    264 # 2: interface 
    265 network_get_subnets6() { __network_ipaddr "$1" "$2" "address6" "" 1; } 
     112        unset "$1" 
     113        return 1 
     114} 
    266115 
    267116# determine all IPv6 prefixes of given logical interface 
    268117# 1: destination variable 
    269118# 2: interface 
    270 network_get_prefixes6() { __network_ipaddr "$1" "$2" "prefix6" "" 1; } 
    271  
    272  
    273 __network_gateway() 
    274 { 
    275         local __var="$1" 
    276         local __iface="$2" 
    277         local __family="$3" 
    278         local __inactive="$4" 
    279  
    280         __network_parse_ifstatus "$__iface" || return 1 
    281  
    282         if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then 
    283                 __network_export "$__var" "${__iface}_inactive_gateway${__family}" && \ 
     119network_get_prefixes6() { 
     120        __network_ifstatus "$1" "$2" "['ipv6-prefix'][*]['address','mask']" "/ " 
     121} 
     122 
     123# determine IPv4 gateway of given logical interface 
     124# 1: destination variable 
     125# 2: interface 
     126# 3: consider inactive gateway if "true" (optional) 
     127network_get_gateway() { 
     128        __network_ifstatus "$1" "$2" ".route[@.target='0.0.0.0' && !@.table].nexthop" "" 1 && \ 
     129                return 0 
     130 
     131        [ "$3" = 1 -o "$3" = "true" ] && \ 
     132                __network_ifstatus "$1" "$2" ".inactive.route[@.target='0.0.0.0' && !@.table].nexthop" "" 1 
     133} 
     134 
     135# determine IPv6 gateway of given logical interface 
     136# 1: destination variable 
     137# 2: interface 
     138# 3: consider inactive gateway if "true" (optional) 
     139network_get_gateway6() { 
     140        __network_ifstatus "$1" "$2" ".route[@.target='::' && !@.table].nexthop" "" 1 && \ 
     141                return 0 
     142 
     143        [ "$3" = 1 -o "$3" = "true" ] && \ 
     144                __network_ifstatus "$1" "$2" ".inactive.route[@.target='::' && !@.table].nexthop" "" 1 
     145} 
     146 
     147# determine the DNS servers of the given logical interface 
     148# 1: destination variable 
     149# 2: interface 
     150# 3: consider inactive servers if "true" (optional) 
     151network_get_dnsserver() { 
     152        __network_ifstatus "$1" "$2" "['dns-server'][*]" && return 0 
     153 
     154        [ "$3" = 1 -o "$3" = "true" ] && \ 
     155                __network_ifstatus "$1" "$2" ".inactive['dns-server'][*]" 
     156} 
     157 
     158# determine the domains of the given logical interface 
     159# 1: destination variable 
     160# 2: interface 
     161# 3: consider inactive domains if "true" (optional) 
     162network_get_dnssearch() { 
     163        __network_ifstatus "$1" "$2" "['dns-search'][*]" && return 0 
     164 
     165        [ "$3" = 1 -o "$3" = "true" ] && \ 
     166                __network_ifstatus "$1" "$2" ".inactive['dns-search'][*]" 
     167} 
     168 
     169 
     170# 1: destination variable 
     171# 2: addr 
     172# 3: inactive 
     173__network_wan() 
     174{ 
     175        __network_ifstatus "$1" "" \ 
     176                "[@.route[@.target='$2' && !@.table]].interface" "" 1 && \ 
    284177                        return 0 
    285         fi 
    286  
    287         __network_export "$__var" "${__iface}_gateway${__family}" 
    288         return $? 
    289 } 
    290  
    291 # determine IPv4 gateway of given logical interface 
    292 # 1: destination variable 
    293 # 2: interface 
    294 # 3: consider inactive gateway if "true" (optional) 
    295 network_get_gateway() { __network_gateway "$1" "$2" 4 "${3:-0}"; } 
    296  
    297 # determine IPv6 gateway of given logical interface 
    298 # 1: destination variable 
    299 # 2: interface 
    300 # 3: consider inactive gateway if "true" (optional) 
    301 network_get_gateway6() { __network_gateway "$1" "$2" 6 "${3:-0}"; } 
    302  
    303  
    304 __network_dns() { 
    305         local __var="$1" 
    306         local __iface="$2" 
    307         local __field="$3" 
    308         local __inactive="$4" 
    309  
    310         __network_parse_ifstatus "$__iface" || return 1 
    311  
    312         if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then 
    313                 __network_export "$__var" "${__iface}_inactive_${__field}" && \ 
    314                         return 0 
    315         fi 
    316  
    317         __network_export "$__var" "${__iface}_${__field}" 
    318         return $? 
    319 } 
    320  
    321 # determine the DNS servers of the given logical interface 
    322 # 1: destination variable 
    323 # 2: interface 
    324 # 3: consider inactive servers if "true" (optional) 
    325 network_get_dnsserver() { __network_dns "$1" "$2" dns_server "${3:-0}"; } 
    326  
    327 # determine the domains of the given logical interface 
    328 # 1: destination variable 
    329 # 2: interface 
    330 # 3: consider inactive domains if "true" (optional) 
    331 network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; } 
    332  
    333  
    334 __network_wan() 
    335 { 
    336         local __var="$1" 
    337         local __family="$2" 
    338         local __inactive="$3" 
    339         local __iface 
    340  
    341         for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do 
    342                 if [ "$__iface" != loopback ]; then 
    343                         if __network_gateway "$__var" "$__iface" "$__family" "$__inactive"; then 
    344                                 eval "export -- \"$__var=$__iface\"" 
    345                                 return 0 
    346                         fi 
    347                 fi 
    348         done 
    349  
    350         eval "export -- \"$__var=\"" 
    351         return 1 
     178 
     179        [ "$3" = 1 -o "$3" = "true" ] && \ 
     180                __network_ifstatus "$1" "" \ 
     181                        "[@.inactive.route[@.target='$2' && !@.table]].interface" "" 1 
    352182} 
    353183 
     
    355185# 1: destination variable 
    356186# 2: consider inactive default routes if "true" (optional) 
    357 network_find_wan() { __network_wan "$1" 4 "${2:-0}"; } 
     187network_find_wan() { __network_wan "$1" "0.0.0.0" "$2"; } 
    358188 
    359189# find the logical interface which holds the current IPv6 default route 
    360190# 1: destination variable 
    361191# 2: consider inactive dafault routes if "true" (optional) 
    362 network_find_wan6() { __network_wan "$1" 6 "${2:-0}"; } 
    363  
    364  
    365 __network_device() 
    366 { 
    367         local __var="$1" 
    368         local __iface="$2" 
    369         local __field="$3" 
    370  
    371         __network_parse_ifstatus "$__iface" || return 1 
    372         __network_export "$__var" "${__iface}_${__field}" 
    373         return $? 
    374 } 
     192network_find_wan6() { __network_wan "$1" "::" "$2"; } 
    375193 
    376194# test whether the given logical interface is running 
     
    379197{ 
    380198        local __up 
    381         __network_device __up "$1" up && [ $__up -eq 1 ] 
     199        __network_ifstatus "__up" "$1" ".up" && [ "$__up" = 1 ] 
    382200} 
    383201 
     
    385203# 1: destination variable 
    386204# 2: interface 
    387 network_get_protocol() { __network_device "$1" "$2" proto; } 
     205network_get_protocol() { __network_ifstatus "$1" "$2" ".proto"; } 
    388206 
    389207# determine the layer 3 linux network device of the given logical interface 
    390208# 1: destination variable 
    391209# 2: interface 
    392 network_get_device() { __network_device "$1" "$2" l3_device; } 
     210network_get_device() { __network_ifstatus "$1" "$2" ".l3_device"; } 
    393211 
    394212# determine the layer 2 linux network device of the given logical interface 
    395213# 1: destination variable 
    396214# 2: interface 
    397 network_get_physdev() { __network_device "$1" "$2" device; } 
    398  
    399  
    400 __network_defer() 
    401 { 
    402         local __device="$1" 
    403         local __defer="$2" 
    404  
    405         json_init 
    406         json_add_string name "$__device" 
    407         json_add_boolean defer "$__defer" 
    408  
    409         ubus call network.device set_state "$(json_dump)" 2>/dev/null 
    410 } 
     215network_get_physdev() { __network_ifstatus "$1" "$2" ".device"; } 
    411216 
    412217# defer netifd actions on the given linux network device 
    413218# 1: device name 
    414 network_defer_device() { __network_defer "$1" 1; } 
     219network_defer_device() 
     220{ 
     221        ubus call network.device set_state \ 
     222                "$(printf '{ "name": "%s", "defer": true }' "$1")" 2>/dev/null 
     223} 
    415224 
    416225# continue netifd actions on the given linux network device 
    417226# 1: device name 
    418 network_ready_device() { __network_defer "$1" 0; } 
     227network_ready_device() 
     228{ 
     229        ubus call network.device set_state \ 
     230                "$(printf '{ "name": "%s", "defer": false }' "$1")" 2>/dev/null 
     231} 
    419232 
    420233# flush the internal value cache to force re-reading values from ubus 
    421 network_flush_cache() 
    422 { 
    423         local __tmp 
    424         for __tmp in $__NETWORK_CACHE __NETWORK_CACHE; do 
    425                 unset "$__tmp" 
    426         done 
    427 } 
     234network_flush_cache() { unset __NETWORK_CACHE; } 
Note: See TracChangeset for help on using the changeset viewer.