1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
|
<pre>Network Working Group G. Trewitt
Request for Comments: 1076 Stanford University
Obsoletes: RFC <a href="./rfc1023">1023</a> C. Partridge
BBN/NNSC
November 1988
<span class="h1">HEMS Monitoring and Control Language</span>
TABLE OF CONTENTS
<span class="h2"><a class="selflink" id="section-1" href="#section-1">1</a>. Status of This Memo </span> 1
Introduction 2
<span class="h2"><a class="selflink" id="section-2" href="#section-2">2</a>. Overview and Scope </span> 2
<span class="h2"><a class="selflink" id="section-3" href="#section-3">3</a>. Overview of Query Processor Operation </span> 4
<span class="h2"><a class="selflink" id="section-4" href="#section-4">4</a>. Encoding of Queries and Responses </span> 5
<span class="h3"><a class="selflink" id="section-4.1" href="#section-4.1">4.1</a> Notation Used in This Proposal </span> 5
<span class="h2"><a class="selflink" id="section-5" href="#section-5">5</a>. Data Organization </span> 6
<span class="h3"><a class="selflink" id="section-5.1" href="#section-5.1">5.1</a> Example Data Tree </span> 7
<span class="h3"><a class="selflink" id="section-5.2" href="#section-5.2">5.2</a> Arrays </span> 8
<span class="h2"><a class="selflink" id="section-6" href="#section-6">6</a>. Components of a Query </span> 9
<span class="h2"><a class="selflink" id="section-7" href="#section-7">7</a>. Reply to a Query </span> 10
<span class="h2"><a class="selflink" id="section-8" href="#section-8">8</a>. Query Language </span> 12
<span class="h3"><a class="selflink" id="section-8.1" href="#section-8.1">8.1</a> Moving Around in the Data Tree </span> 14
<span class="h3"><a class="selflink" id="section-8.2" href="#section-8.2">8.2</a> Retrieving Data </span> 15
<span class="h3"><a class="selflink" id="section-8.3" href="#section-8.3">8.3</a> Data Attributes </span> 16
<span class="h3"><a class="selflink" id="section-8.4" href="#section-8.4">8.4</a> Examining Memory </span> 18
<span class="h3"><a class="selflink" id="section-8.5" href="#section-8.5">8.5</a> Control Operations: </span>Modifying the Data Tree 19
<span class="h3"><a class="selflink" id="section-8.6" href="#section-8.6">8.6</a> Associative Data Access: </span>Filters 21
<span class="h3"><a class="selflink" id="section-8.7" href="#section-8.7">8.7</a> Terminating a Query </span> 26
<span class="h2"><a class="selflink" id="section-9" href="#section-9">9</a>. Extending the Set of Values </span> 27
<span class="h2"><a class="selflink" id="section-10" href="#section-10">10</a>. Authorization </span> 27
<span class="h2"><a class="selflink" id="section-11" href="#section-11">11</a>. Errors </span> 28
<span class="h2"><a class="selflink" id="appendix-I" href="#appendix-I">I</a>. ASN.1 Descriptions of Query Language Components 29</span>
<span class="h3"><a class="selflink" id="appendix-I.1" href="#appendix-I.1">I.1</a> Operation Codes 30</span>
<span class="h3"><a class="selflink" id="appendix-I.2" href="#appendix-I.2">I.2</a> Error Returns 31</span>
<span class="h3"><a class="selflink" id="appendix-I.3" href="#appendix-I.3">I.3</a> Filters 33</span>
<span class="h3"><a class="selflink" id="appendix-I.4" href="#appendix-I.4">I.4</a> Attributes 34</span>
<span class="h3"><a class="selflink" id="appendix-I.5" href="#appendix-I.5">I.5</a> VendorSpecific 36</span>
II. Implementation Hints 36
III. Obtaining a Copy of the ASN.1 Specification 42
<span class="h2"><a class="selflink" id="section-1" href="#section-1">1</a>. STATUS OF THIS MEMO</span>
This RFC specifies a query language for monitoring and control of
network entities. This RFC supercedes <a href="./rfc1023">RFC-1023</a>, extending the query
language and providing more discussion of the underlying issues.
<span class="grey">Trewitt & Partridge [Page 1]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-2" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
This language is a component of the High-Level Entity Monitoring
System (HEMS) described in <a href="./rfc1021">RFC-1021</a> and <a href="./rfc1022">RFC-1022</a>. Readers may wish
to consult these RFCs when reading this memo. <a href="./rfc1024">RFC-1024</a> contains
detailed assignments of numbers and structures used in this system.
Portions of <a href="./rfc1024">RFC-1024</a> that define query language structures are
superceded by definitions in this memo. This memo assumes a
knowledge of the ISO data encoding standard, ASN.1.
Distribution of this memo is unlimited.
INTRODUCTION
This RFC specifies the design of a general-purpose, yet efficient,
monitoring and control language for managing network entities. The
data in the entity is modeled as a hierarchy and specific items are
named by giving the path from the root of the tree. Most items are
read-only, but some can be "set" in order to perform control
operations. Both requests and responses are represented using the
ISO ASN.1 data encoding rules.
<span class="h2"><a class="selflink" id="section-2" href="#section-2">2</a>. OVERVIEW AND SCOPE</span>
The basic model of monitoring and control used in this memo is that a
query is sent to a monitored entity and the entity sends back a
response. The term query is used in the database sense -- it may
request information, modify data, or both. We will use gateway-
oriented examples, but it should be understood that this query-
response mechanism is applicable to any IP entity.
In particular, there is no notion of an interactive "conversation" as
in SMTP [<a href="./rfc821">RFC-821</a>] or FTP [<a href="./rfc959">RFC-959</a>]. A query is a complete request
that stands on its own and elicits a complete response.
In order to design the query language, we had to define a model for
the data to be retrieved by the queries, which required some
understanding of and assumptions to be made about the data. We ended
up with a fairly flexible data model, which places few limits on the
type or size of the data.
Wherever possible, we give motivations for the design decisions or
assumptions that led to particular features or definitions. Some of
the important global considerations and assumptions are:
- The query processor should place as little computational
burden on the monitored entity as possible.
- It should not be necessary for a monitored entity to store
the complete query. Nothing in the query language should
<span class="grey">Trewitt & Partridge [Page 2]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-3" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
preclude an implementation from being able to process the
query on the fly, producing portions of the response while
the query is still being read and parsed. There may be
other constraints that require large amounts of data to be
buffered, but the query language design must not be one.
- It is assumed that there is some mechanism to transport a
sequence of octets to a query processor within the
monitored entity and that there is some mechanism to return
a sequence of octets to the entity making the query. In
HEMS, this is provided by HEMP and its underlying transport
layer. The query language design is independent of these
details, however, and could be grafted onto some other
protocol.
- The data model must provide organization for the data, so
that it can be conveniently named.
- Much of the data to be monitored will be contained in
tables. Some tables may contain other tables. The query
language should be able to deal with such tables.
- We don't provide capabilities for data reduction in the
query language. We will provide for data selection, for
example, only retrieving certain table entries, but we will
not provide general facilities for processing data, such as
computing averages.
- Because one monitoring center may be querying many
(possibly hetrogenous) hosts, it must be possible to write
generic queries that can be sent to all hosts, and have the
query elicit as much information as is available from each
host. i.e., queries must not be aborted just because they
requested non-existent data.
There were some assumptions that we specifically did not make:
- It is up to the implementation to choose what degree of
concurrency will be allowed when processing queries. By
locking only portions of the database, it should be
possible to achieve good concurrency while still preventing
deadlock.
- This specification makes no statement about the use of the
"definite" and "indefinite" length forms in ASN.1. There
is currently some debate about this usage in the ISO
community; implementors should note the recommendations in
the ASN.1 specification.
<span class="grey">Trewitt & Partridge [Page 3]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-4" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
Other RFCs associated with HEMS are:
<a href="./rfc1021">RFC-1021</a> Overview;
<a href="./rfc1022">RFC-1022</a> Transport protocol and message encapsulation;
<a href="./rfc1024">RFC-1024</a> Precise data definitions.
The rest of this report is organized as follows:
<a href="#section-3">Section 3</a> Gives a brief overview of the data model and the
operation of the query processor.
<a href="#section-4">Section 4</a> Describes the encoding used for queries and
responses, and the notation used to represent them
in this report.
<a href="#section-5">Section 5</a> Describes how the data is organized in the
monitored entity, and the view provided of it by
the query processor.
<a href="#section-6">Section 6</a> Describes the basic data types that may be given
to the query processor as input.
<a href="#section-7">Section 7</a> Describes how a reply to a query is organized.
<a href="#section-8">Section 8</a> Describes the operations available in the query
language.
<a href="#section-9">Section 9</a> Describes how the set of data in the tree may be
extended.
<a href="#section-10">Section 10</a> Describes how authorization issues affect the
execution of a query.
<a href="#section-11">Section 11</a> Describes how errors are reported, and their
effect on the processing of the query.
<a href="#appendix-I">Appendix I</a> Gives precise ASN.1 definitions of the data types
used by the query processor.
<a href="#appendix-I">Appendix I</a>I Gives extensive implementation hints for the core
of the query processor.
<span class="h2"><a class="selflink" id="section-3" href="#section-3">3</a>. OVERVIEW OF QUERY PROCESSOR OPERATION</span>
In this section, we give an overview of the operation of the query
processor, to provide a framework for the later sections.
The query language models the manageable data as a tree, with each
<span class="grey">Trewitt & Partridge [Page 4]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-5" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
branch representing a different aspect of the entity, such as
different layers of protocols. Subtrees are further divided to
provide additional structure to the data. The leaves of the tree
contain the actual data.
Given this data representation, the task of the query processor is to
traverse this tree and retrieve (or modify) data specified in a
query. A query consists of instructions to move around in the tree
and to retrieve (or modify) named data. The result of a query is an
exact image of the parts of the tree that the query processor
visited.
The query processor is very simple -- it only understands eight
commands, most of which share the same structure. It is helpful to
think of the query processor as an automaton that walks around in the
tree, directed by commands in the query. As it moves around, it
copies the tree structure it traverses to the query result. Data
that is requested by the query is copied into the result as well.
Data that is changed by a query is copied into the result after the
modification is made.
<span class="h2"><a class="selflink" id="section-4" href="#section-4">4</a>. ENCODING OF QUERIES AND RESPONSES</span>
Both queries and responses are encoded using the representation
defined in ISO Standard ASN.1 (Abstract Syntax Notation 1). ASN.1
represents data as sequences of <tag,length,contents> triples that
are encoded as a stream of octets. The data tuples may be
recursively nested to represent structured data such as arrays or
records. For a full description, see the ISO standards IS 8824 and
IS 8825. See appendix for information about obtaining these
documents.
<span class="h3"><a class="selflink" id="section-4.1" href="#section-4.1">4.1</a> Notation Used in This Proposal</span>
The notation used in this memo is similar to that used in ASN.1, but
less formal, smaller, and (hopefully) easier to read. We will refer
to a <tag,length,contents> tuple as a "data object". In this RFC, we
will not be concerned with the details of the object lengths. They
exist in the actual ASN.1 encoding, but will be omitted in the
examples here.
Data objects that have no internal ASN.1 structure such as integer or
octet string are referred to as "simple types" or "simple objects".
Objects which are constructed out of other ASN.1 data objects will be
referred to as "composite types" or "composite objects".
<span class="grey">Trewitt & Partridge [Page 5]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-6" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
The notation
ID(value)
represents a simple object whose tag is "ID" with the given value. A
composite object is represented as
ID{ ... contents ... }
where contents is a sequence of data objects. The contents may
include both simple and structured types, so the structure is fully
recursive.
The difference between simple and composite types is close to the
meaning of the "constructor" bit in ASN.1. For the uses here, the
distinction is made based upon the semantics of the data, not the
representation. Therefore, even though an OctetString can be
represented in ASN.1 using either constructed or non-constructed
forms, it is conceptually a simple type, with no internal structure,
and will always be written as
ID("some arbitrary string")
in this RFC.
There are situations where it is necessary to specify a type but give
no value, such as when referring to the name of the data. In this
situation, the same notation is used, but with the value omitted:
ID or ID() or ID{}
Such objects have zero length and no contents. The latter two forms
are used when a distinction is being made between simple and
composite data, but the difference is just notation -- the
representation is the same.
ASN.1 distinguishes between four "classes" of tags: universal,
application-specific, context-dependent, and reserved. HEMS and this
query language use the first three. Universal tags are assigned in
the ASN.1 standard and its addendums for common types, and are
understood by any application using ASN.1. Application-specific tags
are limited in scope to a particular application. These are used for
"well-known" identifiers that must be recognizable in any context,
such as derived data types. Finally, context-dependent tags are used
for objects whose meaning is dependent upon where they are
encountered. Most tags that identify data are context-dependent.
<span class="h2"><a class="selflink" id="section-5" href="#section-5">5</a>. DATA ORGANIZATION</span>
Data in a monitored entity is modeled as a hierarchy.
Implementations are not required to organize the data internally as a
hierarchy, but they must provide this view of the data through the
query language. A hierarchy offers useful structure for the
following operations:
<span class="grey">Trewitt & Partridge [Page 6]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-7" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
Organization A hierarchy allows related data to be grouped
together in a natural way.
Naming The name of a piece of data is just the path from the
root to the data of interest.
Mapping onto ASN.1
ASN.1 can easily represent a hierarchy by using a
"constructor" type as an envelope for an entire
subtree.
Efficient Representation
Hierarchical structures are compact and can be
traversed quickly.
Safe Locking If it is necessary to lock part of the hierarchy (for
example, when doing an update), locking an entire
subtree can be done efficiently and safely, with no
danger of deadlock.
We will use the term "data tree" to refer to this entire structure.
Note that this internal model is completely independent of the
external ASN.1 representation -- any other suitable representation
would do. For the sake of efficiency, we do make a one-to-one
mapping between ASN.1 tags and the (internal) names of the nodes.
The same could be done for any other external representation.
Each node in the hierarchy must have names for its component parts.
Although we would normally think of names as being ASCII strings such
as "input errors", the actual name is just an ASN.1 tag. Such names
are small integers (typically, less than 30) and so can easily be
mapped by the monitored entity onto its internal representation.
We use the term "dictionary" to mean an internal node in the
hierarchy. Leaf nodes contain the actual data. A dictionary may
contain both leaf nodes and other dictionaries.
<span class="h3"><a class="selflink" id="section-5.1" href="#section-5.1">5.1</a> Example Data Tree</span>
Here is a possible organization of the hierarchy in an entity that
has several network interfaces and does IP routing. The exact
organization of data in entities is specified in <a href="./rfc1024">RFC-1024</a>. This
skeletal data tree will be used throughout this RFC in query
examples.
System {
name -- host name
clock-msec -- msec since boot
<span class="grey">Trewitt & Partridge [Page 7]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-8" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
interfaces -- # of interfaces
memory
}
Interfaces { -- one per interface
InterfaceData{ address, mtu, netMask, ARP{...}, ... }
InterfaceData{ address, mtu, netMask, ARP{...}, ... }
:
}
IPRouting {
Entry{ ip-addr, interface, cost, ... }
Entry{ ip-addr, interface, cost, ... }
:
}
There are three top-level dictionaries in this hierarchy (System,
Interfaces, and IPRouting) and three other dictionary types
(InterfaceData, Entry, and ARP), each with multiple instances.
The "name" of the clock in this entity would be:
system{ clock-msec }
and the name of a routing table entry's IP address would be:
IPRouting{ Entry{ ip-addr } }.
More than one piece of data can be named by a single ASN.1 object.
The entire collection of system information is named by:
system
and the name of a routing table's IP address and cost would be:
IPRouting{ Entry{ ip-addr, cost } }.
<span class="h3"><a class="selflink" id="section-5.2" href="#section-5.2">5.2</a> Arrays</span>
There is one sub-type of a dictionary that is used as the basis for
tables of objects with identical types. We call these dictionaries
arrays. In the example above, the dictionaries for interfaces,
routing tables, and ARP tables are all arrays.
In the examples above, the "ip-addr" and "cost" fields are named. In
fact, these names refer to the field values for ALL of the routing
table entries -- the name doesn't (and can't) specify which routing
table entry is intended. This ambiguity is a problem wherever data
is organized in tables. If there was a meaningful index for such
tables (e.g., "routing table entry #1"), there would be no problem.
Unfortunately, there usually isn't such an index. The solution to
this problem requires that the data be accessed on the basis of some
of its content. Filters, discussed in <a href="#section-8.6">section 8.6</a>, provide this
mechanism.
The primary difference between arrays and plain dictionaries is that
<span class="grey">Trewitt & Partridge [Page 8]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-9" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
arrays may contain only one type of item, while dictionaries, in
general, will contain many different types of items. For example,
the dictionary IPRouting (which is an array) will contain only items
of type Entry.
The fact that these objects are viewed externally as arrays or tables
does not mean that they are represented in an implementation as
linear lists of objects. Any collection of same-typed objects is
viewed as an array, even though it might be stored internally in some
other format, for example, as a hash table.
<span class="h2"><a class="selflink" id="section-6" href="#section-6">6</a>. COMPONENTS OF A QUERY</span>
A HEMS query consists of a sequence of ASN.1 objects, interpreted by
a simple stack-based interpreter. [Although we define the query
language in terms of the operations of a stack machine, the language
does not require an implementation to use a stack machine. This is a
well-understood model, and is easy to implement.] One ASN.1 tag is
reserved for operation codes; all other tags indicate data that will
eventually be used by an operation. These objects are pushed onto
the stack when received. Opcodes are immediately executed and may
remove or add items to the stack. Because ASN.1 itself provides
tags, very little needs to be done to the incoming ASN.1 objects to
make them suitable for use by the query interpreter.
Each ASN.1 object in a query will fit into one of the following
categories:
Opcode An opcode tells the query interpreter to perform an action.
They are described in detail in <a href="#section-8">section 8</a>. Opcodes are
represented by an application-specific type whose value
determines the operation.
Template These are objects that name one or more items in the data
tree. Named items may be either simple items (leaf nodes)
or entire dictionaries, in which case the entire subtree
"underneath" the dictionary is understood. Templates are
used to select specific data to be retrieved from the data
tree. A template may be either simple or structured,
depending upon what it is naming. A template only names
the data -- there are no values contained in it. Therefore
the leaf objects in a template will all have a length of
zero.
Examples of very simple templates are:
name() or System{}
Each of these is just one ASN.1 data object, with zero
length. The first names a single data item in the "System"
<span class="grey">Trewitt & Partridge [Page 9]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-10" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
dictionary (and must appear in that context), and the
second names the entire "System" dictionary. A more
complex template such as:
Interfaces{ InterfaceData{ address, netMask, ARP } }
names two simple data items and a dictionary, iterated over
all occurrences of "InterfaceData" within the Interfaces
array.
Path A path is a special case of a template that names only a
single node in the tree. It specifies a path down into the
dictionary tree and names exactly one node in the
dictionary tree.
Value These are used to give data values when needed in a query,
for example, when changing a value in the data tree. A
value can be thought of as either a filled-in template or
as the ASN.1 representation some part of the data tree.
Filter A boolean expression that can be executed in the context of
a particular dictionary that is used to select or not
select items in the dictionary. The expressions consist of
the primitives "equal", "greater-or-equal",
"less-or-equal", and "present" possibly joined by "and",
"or", and "not". (See <a href="#section-8.6">section 8.6</a>.)
Values, Paths, and Templates usually have names in the context-
dependent class, except for a few special cases, which are in the
application-specific class.
<span class="h2"><a class="selflink" id="section-7" href="#section-7">7</a>. REPLY TO A QUERY</span>
The data returned to the monitoring entity is a sequence of ASN.1
data items. Conceptually, the reply is a subset of the data tree,
where the query selects which portions are to be included. This is
exactly true for data retrieval requests, and essentially true for
data modification requests -- the reply contains the data after it
has been modified. The key point is that the data in a reply
represents the state of the data tree immediately after the query was
executed.
The sequence of the data is determined by the sequence of query
language operations and the order of data items within Templates and
Values given as input to these operations. If a query requests data
from two of the top-level dictionaries in the data tree, by giving
two templates such as:
System{ name, interfaces }
Interfaces{
<span class="grey">Trewitt & Partridge [Page 10]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-11" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
InterfaceData { address, netMask, mtu }
}
then the response will consist of two ASN.1 data objects, as follows:
System {
name("system name"),
interfaces(2)
}
Interfaces {
InterfaceData { address(36.8.0.1),
netMask(FFFF0000),
mtu(1500)
}
InterfaceData { address(10.1.0.1),
mtu(1008),
netMask(FF000000)
}
}
With few exceptions, each of the data items in the hierarchy is named
in the context-specific ASN.1 type space. Because of this, the
returned objects must be fully qualified. For example, the name of
the entity must always be returned encapsulated inside an ASN.1
object for "System". If it were not, there would be no way to tell
if the object that was returned was "name" inside the "System"
dictionary or "address" inside the "interfaces" dictionary (assuming
in this case that "name" and "address" were assigned the same integer
as their ASN.1 tags).
Having fully-qualified data simplifies decoding of the data at the
receiving end and allows the tags to be locally chosen. Definitions
for tags within routing tables won't conflict with definitions for
tags within interfaces. Therefore, the people doing the name
assignments are less constrained. In addition, most of the
identifiers will be fairly small integers, which is an advantage
because ASN.1 can fit tag numbers up to 30 in a one-octet tag field.
Larger numbers require a second octet.
If data is requested that doesn't exist, either because the tag is
not defined, or because an implementation doesn't provide that data
(such as when the data is optional), the response will contain an
ASN.1 object that is empty. The tag will be the same as in the
query, and the object will have a length of zero.
The same response is given if the requested data does exist, but the
invoker of the query does not have authorization to access it. See
<a href="#section-10">section 10</a> for more discussion of authorization mechanisms.
<span class="grey">Trewitt & Partridge [Page 11]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-12" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
This allows completely generic queries to be composed without regard
to whether the data is defined or implemented at all of the entities
that will receive the query. All of the available data will be
returned, without generating errors that might otherwise terminate
the processing of the query.
<span class="h2"><a class="selflink" id="section-8" href="#section-8">8</a>. QUERY LANGUAGE</span>
The query language is designed to be expressive enough to write
useful queries with, yet simple enough to be easy to implement. The
query processor should be as simple and fast as possible, in order to
avoid placing a burden on the monitored entity, which may be a
critical node such as a gateway.
Although queries are formed in a flexible way using what we term a
"language", this is not a programming language. There are operations
that operate on data, but most other features of programming
languages are not present. In particular:
- Programs are not stored in the query processor.
- The only form of temporary storage is a stack, of limited
depth.
- There are no subroutines.
- There are no explicit control structures defined in the
language.
The central element of the language is the stack. It may contain
templates, (and therefore paths), values, and filters taken from the
query. In addition, it can contain dictionaries (and therefore
arrays) from the data tree. At the beginning of a query, it contains
one item, the root dictionary.
The overall operation consists of reading ASN.1 objects from the
input stream. All objects that aren't opcodes are pushed onto the
stack as soon as they are read. Each opcode is executed immediately
and may remove items from the stack, may generate ASN.1 objects and
send them to the output stream, and may leave items on the stack.
Because each input object is dealt with immediately, portions of the
response may be generated while the query is still being received.
In the descriptions below, operator names are in capital letters,
preceded by the arguments used from the stack and followed by results
left on the stack. For example:
<span class="grey">Trewitt & Partridge [Page 12]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-13" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
OP a b OP a t
means that the OP operator takes <a> and <b> off of the
stack and leaves <t> on the stack. Most of the operators
in the query language leave the first operand (<a> in this
example) on the stack for future use.
If both <a> and <b> were received as part of the query (as opposed to
being calculated by previous operations), then this part of the query
would have consisted of the sequence:
<a>
<b>
OP
So, like other stack-based languages, the arguments and operators
must be presented in postfix order, with an operator following its
operands.
Here is a summary of all of the operators defined in the query
language. Most of the operators can take several different sets of
operands and behave differently based upon the operand types.
Details and examples are given later.
BEGIN dict1 path BEGIN dict1 dict
array path filter BEGIN array dict
Move down in the data tree, establishing a context for
future operations.
END dict END --
Undo the most recent BEGIN.
GET dict GET dict
dict template GET dict
array template filter GET array
Retrieve data from the data tree.
GET-ATTRIBUTES
dict GET-ATTRIBUTES dict
dict template GET-ATTRIBUTES dict
array template filter GET-ATTRIBUTES array
Retrieve attribute information about data in the data tree.
GET-RANGE dict path start length GET-RANGE dict
Retrieve a subrange of an OctetString. Used for reading
memory.
SET dict value SET dict
array value filter SET array
Change values in the data tree, possibly performing control
functions.
<span class="grey">Trewitt & Partridge [Page 13]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-14" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
CREATE array value CREATE dict
Create new table entries.
DELETE array filter DELETE array
Delete table entries.
These operators are defined so that it is impossible to generate an
invalid query response. Since a response is supposed to be a
snapshot of a portion (or portions) of the data tree, it is important
that only data that is actually in the tree be put in the response.
Two features of the language help guarantee this:
- Data is put in the response directly from the tree (by
GET-*). Data does not go from the tree to the stack and
then into the response.
- Dictionaries on the stack are all derived from the initial,
root dictionary. The operations that manipulate
dictionaries (BEGIN and END) also update the response with
the new location in the tree.
<span class="h3"><a class="selflink" id="section-8.1" href="#section-8.1">8.1</a> Moving Around in the Data Tree</span>
The initial point of reference in the data tree is the root. That
is, operators name data starting at the root of the tree. It is
useful to be able to move to some other dictionary in the tree and
then name data from that point. The BEGIN operator moves down in the
tree and END undoes the last unmatched BEGIN.
BEGIN is used for two purposes:
- By moving to a dictionary closer to the data of interest,
the name of the data can be shorter than if the full name
(from the root) were given.
- It is used to establish a context for filtered operations
to operate in. Filters are discussed in <a href="#section-8.6">section 8.6</a>.
BEGIN dict1 path BEGIN dict1 dict
Follow <path> down the dictionary starting from <dict1>.
Push the final dictionary named by <path> onto the stack.
<path> must name a dictionary (not a leaf node). At the
same time, produce the beginning octets of an ASN.1 object
corresponding to the new dictionary. It is up to the
implementation to choose between using the "indefinite
length" representation or the "definite length" form and
going back and filling the length in later.
<span class="grey">Trewitt & Partridge [Page 14]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-15" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
END dict END --
Pop <dict> off of the stack and terminate the open ASN.1
object(s) started by the matching BEGIN. Must be paired
with a BEGIN. If an END operation pops the root dictionary
off of the stack, the query is terminated.
<path> must point to a regular dictionary. If any part of it refers
to a non-existent node, if it points to a leaf node, or if it refers
to a node inside an array-type dictionary, then it is in error, and
the query is terminated immediately.
An additional form of BEGIN, which takes a filter argument, is
described later.
<span class="h3"><a class="selflink" id="section-8.2" href="#section-8.2">8.2</a> Retrieving Data</span>
The basic model that all of the data retrieval operations follow is
that they take a template and fill in the leaf nodes of the template
with the appropriate data values.
GET dict template GET dict
Emit an ASN.1 object with the same "shape" as the given
template, except with values filled in for each node. The
first ASN.1 tag of <template> should refer to an object in
<dict>. If a dictionary tag is supplied anywhere in
<template>, the entire dictionary contents are emitted to
the response. Any items in the template that are not in
<dictionary> (or its components) are represented as objects
with a length of zero.
dict GET dict
If there is no template, get all of the items in the
dictionary. This is equivalent to providing a template
that lists all of the items in the dictionary.
An additional form of GET, which takes a filter argument, is
described later.
Here is an example of using the BEGIN operator to move down the data
tree to the TCP dictionary and then using the GET operator to
retrieve 5 data values from the TCP Stats dictionary:
IPTransport{ TCP } BEGIN
Stats{ octetsIn, octetsOut, inputPkts, outputPkts, badtag } GET
END
<span class="grey">Trewitt & Partridge [Page 15]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-16" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
This might return:
IPTransport{ TCP
Stats{ octetsIn(13255), octetsOut(82323),
inputPkts(9213), outputPkts(12425), badtag() }
}
"badtag" is a tag value that is undefined. No value is returned for
it, indicating that there is no data value associated with it.
<span class="h3"><a class="selflink" id="section-8.3" href="#section-8.3">8.3</a> Data Attributes</span>
Although ASN.1 "self-describes" the structure and syntax of the data,
it gives no information about what the data means. For example, by
looking at the raw data, it is possible to tell that an item is of
type [context 5] and is 4 octets long. That does not tell how to
interpret the data (is this an integer, an IP address, or a 4-
character string?) or what the data means (IP address of what?).
Even if the data were "tagged", in ASN.1 parlance, that would only
give the base type (e.g., IP-address or counter) and not the meaning.
Most of the time, this information will come from <a href="./rfc1024">RFC-1024</a>, which
defines the ASN.1 tags and their precise meaning. When extensions
have been made, it may not be possible to get documentation on the
extensions. (Extensions are discussed in <a href="#section-9">section 9</a>.)
The GET-ATTRIBUTES operator is similar to the GET operator, but
returns a set of attributes describing the data rather than the data
itself. This information is intended to be sufficient to let a human
understand the meaning of the data and to let a sophisticated
application treat the data appropriately. Such an application could
use the attribute information to format the data on a display and
decide whether it is appropriate to subtract one sample from another.
Some of the attributes are textual descriptions to help a human
understand the nature of the data and provide meaningful labels for
it. Extensive descriptions of standard data are optional, since they
are defined in <a href="./rfc1024">RFC-1024</a>. Complete descriptions of extensions must be
available, even if they are documented in a user's manual. Network
firefighters may not have a current manual handy when the network is
broken.
The format of the attributes is not as simple as the format of the
data itself. It isn't possible to use the data's tag, since that
would look exactly like the data itself. The format is:
Attributes ::= [APPLICATION 3] IMPLICIT SEQUENCE {
tagASN1 [0] IMPLICIT INTEGER,
<span class="grey">Trewitt & Partridge [Page 16]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-17" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
valueFormat [1] IMPLICIT INTEGER,
longDesc [2] IMPLICIT IA5String OPTIONAL,
shortDesc [3] IMPLICIT IA5String OPTIONAL,
unitsDesc [4] IMPLICIT IA5String OPTIONAL,
precision [5] IMPLICIT INTEGER OPTIONAL,
properties [6] IMPLICIT BITSTRING OPTIONAL,
valueSet [7] IMPLICIT SET OF valueDesc OPTIONAL
}
The GET-ATTRIBUTES operator is similar to the GET operator. The
major difference is that dictionaries named in the template do not
elicit data for the entire subtree.
GET-ATTRIBUTES
dict template GET-ATTRIBUTES dict
Emit a single ASN.1 Attributes object for each of the
objects named in <template>. For each of these, the
tagASN1 field will be set to the corresponding tag from the
template. The rest of the fields are set as appropriate
for the data object. Any items in the template that are
not in <dictionary> (or its components) elicit an
Attributes object with a valueFormat of NULL, and no other
descriptive information.
or
dict GET-ATTRIBUTES dict
If there is no template, emit Attribute objects for all of
the items in the dictionary. This is equivalent to
providing a template that lists all of the items in the
dictionary. This allows a complete list of a dictionary's
contents to be obtained.
An additional form of GET-ATTRIBUTES, which takes a filter argument,
is described later.
Here is an example of using the GET-ATTRIBUTES operator to request
attributes for three objects in the System dictionary:
System{ name, badtag, clock-msec } GET-ATTRIBUTES
"badtag" is some unknown tag. The result might be:
System{
Attributes{
tagASN1(name),
valueFormat(IA5String),
longDesc("The primary hostname."),
<span class="grey">Trewitt & Partridge [Page 17]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-18" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
shortDesc("hostname")
},
Attributes{
tagASN1(badtag), valueFormat(NULL)
}
Attributes{
tagASN1(clock-msec),
valueFormat(Integer),
longDesc("milliseconds since boot"),
shortDesc("uptime"), unitsDesc("ms")
precision(4294967296),
properties(1)
}
Note that in this example "name" and "clock-msec" are integer values
for the ASN.1 tags for the two data items. "badtag" is an integer
value that has no corresponding name in this context.
There will always be exactly as many Attributes items in the result
as there are objects in the template. Attributes objects for items
which do not exist in the entity will have a valueFormat of NULL and
none of the optional elements will appear.
[ A much cleaner method would be to store the attributes as
sub-components of the data item of interest. For example,
requesting
System{ clock-msec } GET
would normally just get the value of the data. Asking for an
additional layer down the tree would now get its attributes:
System{ clock-msec{ shortDesc, unitsDesc } GET
would get the named attributes. (The attributes would be
named with application-specific tags.) Unfortunately, ASN.1
doesn't provide a notation to describe this type of
organization. So, we're stuck with the GET-ATTRIBUTES
operator. However, if a cleaner organization were possible,
this decision would have been made differently. ]
<span class="h3"><a class="selflink" id="section-8.4" href="#section-8.4">8.4</a> Examining Memory</span>
Even with the ability to symbolically access all of this information
in an entity, there will still be times when it is necessary to get
to very low levels and examine memory, as in remote debugging
operations. The building blocks outlined so far can easily be
extended to allow memory to be examined.
Memory is modeled as an ordinary object in the data tree, with an
ASN.1 representation of OctetString. Because of the variety of
addressing architectures in existence, the conversion from the
<span class="grey">Trewitt & Partridge [Page 18]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-19" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
internal memory model to OctetString is very machine-dependent. The
only simple case is for byte-addressed machines with 8 bits per byte.
Each address space in an entity is represented by one "memory" data
item. In a one-address-space situation, this dictionary will
probably be in "System" dictionary. If each process has its own
address space, then one "memory" item might exist for each process.
Again, this is very machine-dependent.
Although the GET-RANGE operator is provided primarily for the purpose
of retrieving the contents of memory, it can be used on any object
whose base type is OctetString.
GET-RANGE dict path start length GET-RANGE dict
Get <length> elements of the OctetString, starting at
<start>. <start> and <length> are both ASN.1 INTEGER type.
<path>, starting from <dict>, must specify a node
representing memory, or some other OctetString.
The returned data may not be <length> octets long, since it may take
more than one octet to represent one memory location.
Memory items in the data tree are special in that they will not
automatically be returned when the entire contents of a dictionary
are requested. e.g., If memory is part of the "System" dictionary,
then the query
System GET
will emit the entire contents of the System dictionary, but not the
memory item.
<span class="h3"><a class="selflink" id="section-8.5" href="#section-8.5">8.5</a> Control Operations: </span>Modifying the Data Tree
All of the operators defined so far only allow data in an entity to
be retrieved. By replacing the template argument used in the GET
operators with a value, data in the entity can be changed. Very few
items in the data tree can be changed; those that can are noted in
<a href="./rfc1024">RFC-1024</a>.
Values in the data tree can modified in order to change configuration
parameters, patch routing tables, etc. Control functions, such as
bringing an interface "down" or "up", do not usually map directly to
changing a value. In such cases, an item in the tree can be defined
to have arbitrary side-effects when a value is assigned to it.
Control operations then consist of "setting" this item to an
appropriate command code. Reading the value of such an item might
return the current status. Again, details of such data tree items
are given in <a href="./rfc1024">RFC-1024</a>.
<span class="grey">Trewitt & Partridge [Page 19]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-20" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
This "virtual command-and-status register" model is very powerful,
and can be extended by an implementation to provide whatever controls
are needed. It has the advantage that the control function is
associated with the controlled object in the data tree. In addition,
no additional language features are required to support control
functions, and the same operations used to locate data for retrieval
are used to describe what is being controlled.
For all of the control and data modification operations, the fill-
in-the-blank model used for data retrieval is extended: the response
to an operation is the affected part of the data tree, after the
operation has been executed. Therefore, for normal execution, SET
and CREATE will return the object given as an argument, and DELETE
will return nothing (because the affected portion was deleted).
SET dict value SET dict
Set the value(s) of data in the entity to the value(s)
given in <value>. The result will be the value of the data
after the SET. Attempting to set a non-settable item will
not produce an error, but will yield a result in the reply
different from what was sent.
CREATE array value CREATE dict
Insert a new entry into <array>. Depending upon the
context, there may be severe restrictions about what
constitutes a valid <value>. The result will be the actual
item added to the <array>. Note that only one item can be
added per CREATE operation.
DELETE array filter DELETE array
Delete the entry(s) in <array> that match <filter>.
Filters are described later in this document. Normally, no
data items will be produced in the response, but if any of
the items that matched the filter could not be deleted,
they will be returned in the response.
An additional form of SET, which takes a filter argument, is
described later.
Here is an example of attempting to use SET to change the number of
interfaces in an entity:
System{ interfaces(5) } SET
Since that is not a settable parameter, the result would be:
System{ interfaces(2) }
giving the old value.
Here is an example of how CREATE would be used to add a routing table
entry for net for 128.89.0.0.
<span class="grey">Trewitt & Partridge [Page 20]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-21" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
IPRouting BEGIN -- get dictionary
Entries{ DestAddr(128.89.0.0), ... } -- entry to insert
CREATE
END -- finished with dict
The result would be what was added:
IPRouting{ Entries{ DestAddr(128.89.0.0), ... } }
The results in the response of these operators is consistent of the
global model of the response: it contains a subset of the data in
the tree immediately after the query is executed.
Note that CREATE and DELETE only operate on arrays, and then only on
arrays that are specifically intended for it. For example, it is
quite reasonable to add and remove entries from routing tables or ARP
tables, both of which are arrays. However, it doesn't make sense to
add or remove entries in the "Interfaces" dictionary, since the
contents of that array is dictated by the hardware. For each array
in the data tree, <a href="./rfc1024">RFC-1024</a> indicates whether CREATE and DELETE are
valid.
CREATE and DELETE are always invalid in non-array contexts. If
DELETE were allowed on monitored data, then the deleted data would
become unmonitorable to the entire world. Conversely, if it were
possible to CREATE arbitrary dictionary entries, there would be no
way to give such entries any meaning. Even with the data in place,
there is nothing that would couple the data to the operation of the
monitored entity. [Creation and deletion would also add considerable
complication to an implementation, because without them, all of the
data structures that represent the data tree are essentially static,
with the exception of dynamic tables such as the ones mentioned,
which already have mechanisms in place for adding and removing
entries.]
<span class="h3"><a class="selflink" id="section-8.6" href="#section-8.6">8.6</a> Associative Data Access: </span>Filters
One problem that has not been dealt with was alluded to earlier: When
dealing with array data, how do you specify one or more entries based
upon some value in the array entries? Consider the situation where
there are several interfaces. The data might be organized as:
Interfaces { -- one per interface
InterfaceData { address, mtu, netMask, ARP{...}, ... }
InterfaceData { address, mtu, netMask, ARP{...}, ... }
:
}
If you only want information about one interface (perhaps because
<span class="grey">Trewitt & Partridge [Page 21]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-22" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
there is an enormous amount of data about each), then you have to
have some way to name it. One possibility would be to just number
the interfaces and refer to the desired interface as
InterfaceData(3)
for the third one.
But this is not sufficient, because interface numbers may change over
time, perhaps from one reboot to the next. It is even worse when
dealing with arrays with many elements, such as routing tables, TCP
connections, etc. Large, changing arrays are probably the more
common case, in fact. Because of the lack of utility of indexing in
this context, there is no general mechanism provided in the language
for indexing.
A better scheme is to select objects based upon some value contained
in them, such as the IP address. The query language uses filters to
select specific table entries that an operator will operate on. The
operators BEGIN, GET, GET-ATTRIBUTES, SET, and DELETE can take a
filter argument that restricts their operation to entries that match
the filter.
A filter is a boolean expression that is executed for each element in
an array. If an array entry "matches" the filter (i.e., if the filter
produces a "true" result), then it is used by the operation. A
filter expression is very restricted: it can only compare data
contained in the array element and the comparisons are only against
constants. Comparisons may be connected by AND, OR and NOT
operators.
The ASN.1 definition of a filter is:
Filter ::= [APPLICATION 2] CHOICE {
present [0] DataPath,
equal [1] DataValue,
greaterOrEqual [2] DataValue,
lessOrEqual [3] DataValue,
and [4] SEQUENCE OF Filter,
or [5] SEQUENCE OF Filter,
not [6] Filter
}
DataPath ::= ANY -- Path with no value
DataValue ::= ANY -- Single data value
This definition is similar to the filters used in the ISO monitoring
protocol (CMIP) and was derived from that specification.
<span class="grey">Trewitt & Partridge [Page 22]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-23" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
"DataPath" is the name of a single data item; "DataValue" is the
value of a single data item. The three comparisons are all of the
form "data OP constant", where "data" is the value from the tree,
"constant" is the value from the filter expression, and "OP" is one
of equal, greater-than-or-equal, or less-than-or-equal. The last
operation, "present", tests to see if the named item exists in the
data tree. By its nature, it requires no value, so only a path needs
to be given.
Here is an example of a filter that matches an Interface whose IP
address is 10.1.0.1:
Filter{ equal{ address(10.0.0.51) } }
Note that the name of the data to be compared is relative to the
"InterfaceData" dictionary.
Each operator, when given a filter argument, takes an array
(dictionary containing only one type of item) as its first argument.
In the current example, this would be "Interfaces". The items in it
are all of type "InterfaceData". This tag is referred to as the
"iteration tag".
Before a filtered operation is used, BEGIN must be used to put the
array (dictionary) on top of the stack, to establish it as the
context that the filter iterates over. The general operation of a
filtered operation is then:
1. Iterate over the items in the array.
2. For each element in the array, execute the filter.
3. If the filter succeeds, do the requested operation
(GET/SET/etc.) on the matched element, using the
template/value/path as input to the operation. At this
point, the execution of the operation is the same as in
the non-filtered case.
This is a model of operation; actual implementations may take
advantage of whatever lookup techniques are available for the
particular table (array) involved.
Therefore, there are three inputs to a filtered operation:
1. The "current dictionary" on the stack. This is the
array-type dictionary to be searched, set by an earlier
BEGIN.
2. A filter, to test each item in the array. Each path or
value mentioned in the filter must be named in the context
<span class="grey">Trewitt & Partridge [Page 23]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-24" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
of an item in the array, as if it was the current
dictionary. For example, in the case where a filtered
operation iterates over the set of "InterfaceData" items
in the "Interfaces" array, each value or path in the
filter should name an item in the "InterfaceData"
dictionary, such as "address".
3. A template, path, or value associated with the operation
to be performed. The leading ASN.1 tag in this must match
the iteration tag. In the current example where the
filter is searching the "Interfaces" dictionary, the first
tag in the template/tag/value must be "InterfaceData".
The operators which take filters as arguments are:
BEGIN array path filter BEGIN array dict
Find a dictionary in <array> that matches <filter>. Use
that as the starting point for <path> and push the
dictionary corresponding to <path> onto the stack. If more
than one dictionary matches <filter>, then any of the
matches may be used. This specification does not state how
the choice is made. At least one dictionary must match; it
is an error if there are no matches. (Perhaps it should be
an error for there to be multiple matches; actual
experience is needed to decide.)
GET array template filter GET array
For each item in <array> that matches <filter>, fill in the
template with values from the data tree and emit the
result. The first tag of <template> must be equal to the
iteration tag. Selected parts of matched items are emitted
based upon <template>, just as in a non-filtered GET
operation.
GET-ATTRIBUTES
array template filter GET-ATTRIBUTES array
Same as GET, except emit attributes rather than data
values.
SET array value filter SET array
Same as GET, except set the values in <value> rather than
retrieving values. Several values in the data tree will be
changed if the filter matches more than one item in the
array.
DELETE array filter DELETE array
Delete the entry(s) in <array> that match <filter>.
<span class="grey">Trewitt & Partridge [Page 24]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-25" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
Notes about filter execution:
- Expressions are executed by inorder tree traversal.
- Since the filter operations are all GETs and comparisons,
there are no side-effects to filter execution, so an
implementation is free to execute only as much of the
filter as required to produce a result (e.g., don't execute
the rest of an AND if the first comparison turns out to be
false).
- It is not an error for a filter to test a data item that
isn't in the data tree. In this situation, the comparison
just fails (is false). This means that filters don't need
to test for the existence of optional data before
attempting to compare it.
Here is an example of how filtering would be used to obtain the input
and output packet counts for the interface with IP address 10.0.0.51.
Interfaces BEGIN -- dictionary
InterfaceData{ pktsIn, pktsOut } -- template
Filter{ equal{ address(10.0.0.51) } }
GET
END -- finished with dict
The returned value would be something like:
Interfaces{ -- BEGIN
InterfaceData{ pktsIn(1345134), pktsOut(1023729) }
-- GET
} -- END
The annotations indicate which part of the response is generated by
the different operators in the query.
Here is an example of accessing a table contained within some other
table. Suppose we want to get at the ARP table for the interface
with IP address 36.8.0.1 and retrieve the entire ARP entry for the
host with IP address 36.8.0.23. In order to retrieve a single entry
in the ARP table (using a filtered GET), a BEGIN must be used to get
down to the ARP table. Since the ARP table is contained within the
Interfaces dictionary (an array), a filtered BEGIN must be used.
Interfaces BEGIN -- dictionary
InterfaceData{ ARP } -- path
Filter{ equal{ address(36.8.0.1) } } -- filter
BEGIN -- filtered BEGIN
<span class="grey">Trewitt & Partridge [Page 25]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-26" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
-- Now in ARP table for 38.0.0.1; get entry for 38.8.0.23.
addrMap -- whole entry
Filter{ equal{ ipAddr(36.8.0.23) } } -- filter
GET -- filtered GET
END
END
The result would be:
Interfaces{ -- first BEGIN
InterfaceData{ ARP{ -- second BEGIN
addrMap{ ipAddr(36.8.0.23), physAddr(..) } -- from GET
} } -- first END
} -- second END
Note which parts of the output are generated by different parts of
the query.
Here is an example of how the SET operator would be used to shut down
the interface with ip-address 10.0.0.51 by changing its status to
"down".
Interfaces BEGIN -- get dictionary
Interface{ Status(down) } -- value to set
Filter{ equal{ IP-addr(10.0.0.51) } }
SET
END
If the SET is successful, the result would be:
Interfaces{ -- BEGIN
Interface{ Status(down) } -- from SET
} -- END
<span class="h3"><a class="selflink" id="section-8.7" href="#section-8.7">8.7</a> Terminating a Query</span>
A query is implicitly terminated when there are no more ASN.1 objects
to be processed by the interpreter. For a perfectly-formed query,
the interpreter would be back in the state it was when it started:
the stack would have only the root dictionary on it, and all of the
ASN.1 objects in the result would be terminated.
If there are still "open" ASN.1 objects in the result (caused by
leaving ENDs off of the query), then these are closed, as if a
sufficient number of ENDs were provided. This condition would be
indicated by the existence of dictionaries other than the root
dictionary on the stack.
<span class="grey">Trewitt & Partridge [Page 26]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-27" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
If an extra END is received that would pop the root dictionary off of
the stack, the query is terminated immediately. No error is
generated.
<span class="h2"><a class="selflink" id="section-9" href="#section-9">9</a>. EXTENDING THE SET OF VALUES</span>
There are two ways to extend the set of values understood by the
query language. The first is to register the data and its meaning
and get an ASN.1 tag assigned for it. This is the preferred method
because it makes that data specification available for everyone to
use.
The second method is to use the VendorSpecific application type to
"wrap" the vendor-specific data. Wherever an implementation defines
data that is not in <a href="./rfc1024">RFC-1024</a>, the "VendorSpecific" tag should be used
to label a dictionary containing the vendor-specific data. For
example, if a vendor had some data associated with interfaces that
was too strange to get standard numbers assigned for, they could,
instead represent the data like this:
interfaces {
interface {
in-pkts, out-pkts, ...
VendorSpecific { ephemeris, declination }
}
}
In this case, ephemeris and declination correspond to two context-
dependent tags assigned by the vendor for their non-standard data.
If the vendor-specific method is chosen, the private data MUST have
descriptions available through the GET-ATTRIBUTES operator. Even
with this descriptive ability, the preferred method is to get
standard numbers assigned if possible.
<span class="h2"><a class="selflink" id="section-10" href="#section-10">10</a>. AUTHORIZATION</span>
This specification does not state what type of authorization system
is used, if any. Different systems may have needs for different
mechanisms (authorization levels, capability sets, etc.), and some
systems may not care about authorization at all. The only effect
that an authorization system has on a query is to restrict what data
items in the tree may be retrieved or modified.
Therefore, there are no explicit query language features that deal
with protection. Instead, protection mechanisms are implicit and may
make some of the data invisible (for GET) or non-writable (for SET):
<span class="grey">Trewitt & Partridge [Page 27]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-28" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
- Each query runs with some level of authorization or set of
capabilities, determined by its environment (HEMS and the
HEMP header).
- Associated with each data item in the data tree is some
sort of test to determine if a query's authorization should
grant it access to the item.
Authorization tests are only applied to query language operations
that retrieve information (GET, GET-ATTRIBUTES, and GET-RANGE) or
modify it (SET, CREATE, DELETE). An authorization system must not
affect the operation of BEGIN and END. In particular, the
authorization must not hide entire dictionaries, because that would
make a BEGIN on such a dictionary fail, terminating the entire query.
<span class="h2"><a class="selflink" id="section-11" href="#section-11">11</a>. ERRORS</span>
If some particular information is requested but is not available, it
will be returned as "no-value" by giving the ASN.1 length as 0.
When there is any other kind of error, such as having improper
arguments on the top of the stack or trying to execute BEGIN when the
path doesn't refer to a dictionary, an ERROR object is emitted.
The contents of this object identify the exact nature of the error:
Error ::= [APPLICATION 0] IMPLICIT SEQUENCE {
errorCode INTEGER,
errorInstance INTEGER,
errorOffset INTEGER
errorDescription IA5String,
errorOp INTEGER,
}
errorCode identifies what the error was, and errorInstance is an
implementation-dependent code that gives a more precise indication of
where the error occured. errorOffset is the location within the
query where the error occurred. If an operation was being executed,
errorOp contains its operation code, otherwise zero.
errorDescription is a text string that can be printed that gives some
description of the error. It will at least describe the errorCode,
but may also give details implied by errorInstance. Detailed
definitions of all of the fields are given in <a href="#appendix-I.2">appendix I.2</a>.
Since there may be several unterminated ASN.1 objects in progress at
the time the error occurs, each one must be terminated. Each
unterminated object will be closed with a copy of the ERROR object.
Depending upon the type of length encoding used for this object, this
<span class="grey">Trewitt & Partridge [Page 28]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-29" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
will involve filling the value for the length (definite length form)
or emitting two zero octets (indefinite length form). After all
objects are terminated, a final copy of the ERROR object will be
emitted. This structure guarantees that the error will be noticed at
every level of interpretation on the receiving end.
In summary, if there was an error before any ASN.1 objects were
generated, then the result would simply be:
error{...}
If a couple of ASN.1 objects were unterminated when the error
occurred, the result might look like:
interfaces{
interface { name(...) type(...) error{...} }
error{...}
}
error{...}
It would be possible to define a "WARNING" object that has a similar
(or same) format as ERROR, but that would be used to annotate
responses when a non-fatal "error" occurs, such as attempting to
SET/CREATE/DELETE and the operation is denied. This would be an
additional complication, and we left it out in the interests of
simplicity.
<span class="h2"><a class="selflink" id="appendix-I" href="#appendix-I">I</a>. ASN.1 DESCRIPTIONS OF QUERY LANGUAGE COMPONENTS</span>
A query consists of a sequence of ASN.1 objects, as follows:
Query := IMPLICIT SEQUENCE of QueryElement;
QueryElement ::= CHOICE {
Operation,
Filter,
Template,
Path,
InputValue
}
Operation and Filter are defined below. The others are:
Template ::= any
Path ::= any
InputValue ::= any
These three are all similar, but have different restrictions on their
structure:
<span class="grey">Trewitt & Partridge [Page 29]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-30" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
Template Specifies a portion of the tree, naming one or more
values, but not containing any values.
Path Specifies a single path from one point in the tree to
another, naming exactly one value, but not containing
a value.
InputValue Gives a value to be used by a query language
operator.
A query response consists of a sequence of ASN.1 objects, as follows:
Response := IMPLICIT SEQUENCE of ResponseElement;
ResponseElement ::= CHOICE {
ResultValue,
Error
}
Error is defined below. The others are:
ResultValue ::= any
ResultValue is similar to Template, above:
ResultValue Specifies a portion of the tree, naming and
containing one or more values.
The distinctions between these are elaborated in <a href="#section-6">section 6</a>.
<span class="h3"><a class="selflink" id="appendix-I.1" href="#appendix-I.1">I.1</a> Operation Codes</span>
Operation codes are all encoded in a single application-specific
type, whose value determines the operation to be performed. The
definition is:
Operation ::= [APPLICATION 1] IMPLICIT INTEGER {
reserved(0),
begin(1),
end(2),
get(3),
get-attributes(4),
get-range(5),
set(6),
<span class="grey">Trewitt & Partridge [Page 30]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-31" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
create(7),
delete(8)
}
<span class="h3"><a class="selflink" id="appendix-I.2" href="#appendix-I.2">I.2</a> Error Returns</span>
An Error object is returned within a reply when an error is
encountered during the processing of a query. Note that the
definition this object is similar to that of the HEMP protocol error
structure. The error codes have been selected to keep the code
spaces distinct between the two. This is intended to ease the
processing of error messages. See <a href="#section-11">section 11</a> for more information.
Error ::= [APPLICATION 0] IMPLICIT SEQUENCE {
errorCode INTEGER,
errorInstance INTEGER,
errorOffset INTEGER
errorDescription IA5String,
errorOp INTEGER,
}
The fields are defined as follows:
errorCode Identifies the general cause of the error.
errorInstance An implementation-dependent code that gives a more
precise indication of where the error occured in the
query processor. This is most useful when internal
errors are reported.
errorOffset The location within the query where the error was
detected. The first octet of the query is numbered
zero.
errorOp If an operation was being executed, this contains its
operation code, otherwise zero.
errorDescription
A text string that can be printed that gives some
description of the error. It will at least describe
the errorCode, but may also give details implied by
errorInstance.
Some errors are associated with the execution of specific operations,
and others with the overall operation of the query interpreter. The
errorCodes are split into two groups.
The first group deals with overall interpreter operation. Except for
<span class="grey">Trewitt & Partridge [Page 31]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-32" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
"unknown operation", these do not set errorOp.
100 Other error.
Any error not listed below.
101 Format error.
An error has been detected in the format of the input
stream, preventing further interpretation of the
query.
102 System error.
The query processor has failed in some way due to an
internal error.
103 Stack overflow.
Too many items were pushed on the stack.
104 Unknown operation.
The operation code is invalid. errorOp is set.
The second group is errors that are associated with the execution of
particular operations. errorOp will always be set for these.
200 Other operation error.
Any error, associated with an operation, not listed
below.
201 Stack underflow.
An operation expected to see some number of operands
on the stack, and there were fewer items on the
stack.
202 Operand error.
An operation expected to see certain operand types on
the stack, and something else was there.
203 Invalid path for BEGIN.
A path given for BEGIN was invalid, because some
element in the path didn't exist.
204 Non-dictionary for BEGIN.
A path given for BEGIN was invalid, because the given
node was a leaf node, not a dictionary.
205 BEGIN on array element.
The path specified an array element. The path must
point at a single, unique, node. A filtered BEGIN
should have been used.
<span class="grey">Trewitt & Partridge [Page 32]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-33" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
206 Empty filter for BEGIN.
The filter for a BEGIN didn't match any array
element.
207 Filtered operation on non-array.
A filtered operation was attempted on a regular
dictionary. Filters can only be used on arrays.
208 Index out of bounds.
The starting address or length for a GET-RANGE
operation went outside the bounds for the given
object.
209 Bad object for GET-RANGE.
GET-RANGE can only be applied to objects whose base
type is OctetString.
This list is probably not quite complete, and would need to be
extended, based upon implementation experience.
<span class="h3"><a class="selflink" id="appendix-I.3" href="#appendix-I.3">I.3</a> Filters</span>
Many of the operations can take a filter argument to select among
elements in an array. They are discussed in <a href="#section-8.6">section 8.6</a>.
Filter ::= [APPLICATION 2] CHOICE {
present [0] DataPath,
equal [1] DataValue,
greaterOrEqual [2] DataValue,
lessOrEqual [3] DataValue,
and [4] SEQUENCE OF Filter,
or [5] SEQUENCE OF Filter,
not [6] Filter
}
DataPath ::= ANY -- Path with no value
DataValue ::= ANY -- Single data value
A filter is executed by inorder traversal of its ASN.1 structure.
The basic filter operations are:
present tests for the existence of a particular data item in
the data tree
<span class="grey">Trewitt & Partridge [Page 33]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-34" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
equal tests to see if the named data item is equal to the
given value.
greaterOrEqual tests to see if the named data item is greater than
or equal to the given value.
lessOrEqual tests to see if the named data item is less than or
equal to the given value.
These may be combined with "and", "or", and "not" operators to form
arbitrary boolean expressions. The "and" and "or" operators will
take any number of terms. Terms are only evaluated up to the point
where the outcome of the expression is determined (i.e., an "and"
term's value is false or an "or" term's value is true).
<span class="h3"><a class="selflink" id="appendix-I.4" href="#appendix-I.4">I.4</a> Attributes</span>
One or more Attributes structure is returned by the GET-ATTRIBUTES
operator. This structure provides descriptive information about
items in the data tree. See the discussion in <a href="#section-8.3">section 8.3</a>.
Attributes ::= [APPLICATION 3] IMPLICIT SEQUENCE {
tagASN1 [0] IMPLICIT INTEGER,
valueFormat [1] IMPLICIT INTEGER,
longDesc [2] IMPLICIT IA5String OPTIONAL,
shortDesc [3] IMPLICIT IA5String OPTIONAL,
unitsDesc [4] IMPLICIT IA5String OPTIONAL,
precision [5] IMPLICIT INTEGER OPTIONAL,
properties [6] IMPLICIT BITSTRING OPTIONAL,
valueSet [7] IMPLICIT SET OF valueDesc OPTIONAL
}
valueDesc ::= IMPLICIT SEQUENCE {
value [0] ANY, -- Single data value
desc [1] IA5String
}
The meanings of the various attributes are given below.
tagASN1 The ASN.1 tag for this object. This attribute is
required.
valueFormat The underlying ASN.1 type of the object (e.g.,
SEQUENCE or OCTETSTRING or Counter). This is not
just the tag number, but the entire tag, as it would
appear in an ASN.1 object. As such, it includes the
class, which should be either UNIVERSAL or
APPLICATION. Applications receiving this should
<span class="grey">Trewitt & Partridge [Page 34]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-35" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
ignore the constructor bit. This attribute is
required.
longDesc A potentially lengthy text description which fully
defines the object. This attribute is optional for
objects defined in this memo and required for
entity-specific objects.
shortDesc A short mnemonic string of less than 15 characters,
suitable for labeling the value on a display. This
attribute is optional.
unitsDesc A short string used for integer values to indicate
the units in which the value is measured (e.g., "ms",
"sec", "pkts", etc.). This attribute is optional.
precision For Counter objects, the value at which the Counter
will roll-over. Required for all Counter objects.
properties A bitstring of boolean properties of the object. If
the bit is on, it has the given property. This
attribute is optional. The bits currently defined
are:
0 If true, the difference between two values of
this object is significant. For example, the
changes of a packet count is always significant,
it always conveys information. In this case, the
0 bit would be set. On the other hand, the
difference between two readings of a queue length
may be meaningless.
1 If true, the value may be modified with SET,
CREATE, and DELETE. Applicability of CREATE and
DELETE depends upon whether the object is in an
array.
2 If true, the object is a dictionary, and a BEGIN
may be used on it. If false, the object is leaf
node in the data tree.
3 If true, the object is an array-type dictionary,
and filters may be used to traverse it. (Bit 2
will be true also.)
valueSet For data that is defined as an ASN.1 CHOICE type (an
enumerated type), this gives descriptions for each of
the possible values that the data object may assume.
<span class="grey">Trewitt & Partridge [Page 35]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-36" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
Each valueDesc is a <value,description> pair. This
information is especially important for control
items, which are very likely to appear in
VendorSpecific dictionaries, exactly the situation
where descriptive information is needed.
<span class="h3"><a class="selflink" id="appendix-I.5" href="#appendix-I.5">I.5</a> VendorSpecific</span>
See the discussion in <a href="#section-9">section 9</a>.
VendorSpecific ::= [APPLICATION 4] IMPLICIT SET
of ANY
II. IMPLEMENTATION HINTS
Although it is not normally in the spirit of RFCs to define an
implementation, the authors feel that some suggestions will be useful
to implementors of the query language. This list is not meant to be
complete, but merely to give some hints about how the authors imagine
that the query processor might be implemented efficiently.
- It should be understood that the stack is of very limited
depth. Because of the nature of the query language, it can
get only about 4 entries (for arguments) plus the depth of
the tree (up to one BEGIN per level in the tree). This
comes out to about a dozen entries in the stack, a modest
requirement.
- The stack is an abstraction -- it should be implemented
with pointers, not by copying dictionaries, etc.
- An object-oriented approach should make implementation
fairly easy. Changes to the "shape" if the data items
(which will certainly occur, early on) will also be easier
to make.
- Only a few "messages" need to be understood by objects. By
having pointers to action routines for each basic operation
(GET,SET,...) associated with each node in the tree, common
routines (e.g., emit a long integer located at address X)
can be shared, and special routines (e.g., set the interface
state for interface X) can be implemented in a common
framework. Higher levels need know nothing about what data
is being dealt with.
- Most interesting objects are dictionaries, each of which
can be implemented using pointers to the data and procedure
"hooks" to perform specific operations such as GET, SET,
<span class="grey">Trewitt & Partridge [Page 36]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-37" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
filtering, etc.
- The hardest part is actually extracting the data from
existing TCP/IP implementations that weren't designed with
detailed monitoring in mind. Query processors interfacing
to a UNIX kernel will have to make many system calls in
order to extract some of the more intricate structures,
such as routing tables. This should be less of a problem
if a system is designed with easy monitoring as a goal.
A Skeletal Implementation
This section gives a rather detailed example of the core of a query
processor. This code has not been tested, and is intended only to
give implementors ideas about how to tackle some aspects of query
processor implementation with finesse, rather than brute force.
The suggested architecture is for each dictionary to have a
"traverse" routine associated with it, which is called when any sort
of operation has to be done on that dictionary. Most nodes will
share the same traversal routine, but array dictionaries will usually
have routines that know about whatever special lookup mechanisms are
required.
Non-dictionary nodes would have two routines, "action", and
"compare", which implement query language operations and filter
comparisons, respectively. Most nodes would share these routines.
For example, there should be one "action" routine that does query
language operations on 32-bit integers, and another that works on
16-bit integers, etc.
Any traversal procedure would take arguments like:
traverse(node, mask, op, filter)
Treenode node; /* generic node-in-tree */
ASN mask; /* internal ASN.1 form */
enum opset op; /* what to do */
Filter filter; /* zero if no filter */
enum opset { begin, get, set, create, delete, geta,
c_le, c_ge, c_eq, c_exist };
The traversal procedure is called whenever anything must be done
within a dictionary. The arguments are:
node the current dictionary.
<span class="grey">Trewitt & Partridge [Page 37]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-38" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
mask is either the template, path, or value, depending
upon the operation being performed. The top-level
identifier of this object will be looked up in the
context of <node>.
op is the operation to be performed, either one of the
basic operations, or a filter operation.
filter is the filter to be applied, or zero if none. There
will be no filter when <op> is a filter-comparison
operation.
The general idea is that the traversal proc associated with a node
has all of the knowledge about how to get around in this subtree
encoded within it. Hopefully, this will be the only place this
knowledge is coded. Here is a skeleton of the "standard" traversal
proc, written mostly in C.
When the query processor needs to execute a "GET" operation, it would
just call:
traverse(current, template, GET, 0)
Notes about this example:
- This traversal routine handles either query language
operations (GET, SET, etc.) or low-level filter operations.
Separate routines could be defined for the two classes of
operations, but they do much of the same work.
- Dictionary nodes have a <traversal> proc defined.
- Leaf nodes have an <action> proc, which implement GET, SET,
GET-ATTRIBUTES, CREATE, and DELETE, and a <compare> proc,
which performs low-level filter comparisons.
- In the generic routine, the filter argument is unused,
because the generic routine isn't used for array
dictionaries, and only array dictionaries use filters.
- An ASN type contains the top level tag and a list of
sub-components.
- size(mask) takes an ASN.1 object and tells how many
sub-items are in it. Zero means that this is a simple
object.
- lookup(node, tag) looks up a tag in the given (tree)node,
returning a pointer to the node. If the tag doesn't exist
<span class="grey">Trewitt & Partridge [Page 38]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-39" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
in that node, a pointer to a special node "NullItem" is
returned. NullItem looks like a leaf node and has procs
that perform the correct action for non-existent data.
- This example does not do proper error handling, or ASN.1
generation, both of which would require additional code in
this routine.
/*
* For op = GET/SET/etc, return:
* true on error, otherwise false.
* When op is a filter operation, return:
* the result of the comparison.
*/
int std_traverse(node, mask, op, filter)
Treenode node; /* current node */
ASN mask; /* internal ASN.1 form */
enum opset op; /* what to do */
Filter filter; /* unused in this routine */
{
ASN item;
Treenode target;
boolean rv = false;
extern Treenode NullItem;
if (filter != null) {
error(...);
return true;
}
target = lookup(node, mask.tag);
/* We are at the leaf of the template/path/value. */
if (size(mask) == 0)
switch (op)
{
case BEGIN:
/* non-existent node, or leaf node */
if (target == NullItem || target.traverse == 0) {
error(...);
return true;
}
else {
begin(node, mask.tag);
return false;
}
case GET: case SET: case GETA:
<span class="grey">Trewitt & Partridge [Page 39]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-40" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
case GETR: case CREATE: case DELETE:
/* A leaf in the mask specifies entire directory.
For GET, traverse the entire subtree. */
if (target.traverse)
if (op == GET) {
foreach subnode in target
/* Need to test to not GET memory. */
rv |= (*target.traverse)
(target, subnode.tag, op, 0);
return rv;
}
else if (op == SET) /* no-op */
return false;
else if (op != GETA) {
error(...);
return true;
}
/* We're at a leaf in both the mask and the tree.
Just execute the operation.
*/
else {
if (op == BEGIN) { /* Can't begin on leaf */
error(...);
return true;
else
return (*target.action)(target, mask, op);
}
} /* else */
default: /* Comparison ops. */
return (*target.compare)(target, mask, op);
} /* switch */
/* We only get here if mask has structure. */
/* can't have multiple targets for BEGIN */
if (op == BEGIN && size(mask) != 1) {
error(...);
return true;
}
/* or for a single filter operation. */
if (op is comparison && size(mask) != 1) {
error(...);
return false;
}
/* Iterate over the components in mask */
foreach item in mask
{
<span class="grey">Trewitt & Partridge [Page 40]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-41" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
if (target.traverse) /* traverse subtree. */
rv |= (*component.traverse)(component, item, op, 0);
else /* leaf node, at last. */
if (op is comparison)
return (*target.compare)(target, mask, op);
else
return (*target.action)(target, mask, op);
} /* foreach */
return rv;
} /* std_traverse */
Here is a bare skeleton of an array-type dictionary's traversal proc.
int array_traverse(node, mask, op, filter)
Treenode node; /* current node */
ASN mask; /* internal ASN.1 form */
enum opset op; /* what to do */
Filter filter; /* unused in this routine */
{
Treenode target;
boolean rv = false;
extern Treenode NullItem;
/* Didn't find that key. */
if (mask.tag != this array's iteration tag)
return false;
if (op == BEGIN && filter == null) {
error(...);
return 1;
}
/* The implementation of this loop is the major trick! */
/* Needs to stop after first filter success on BEGIN. */
foreach target in node {
if (filter == null || /* if no filter, or */
ExecFilter(target, filter)) /* if it succeeds */
rv |= (target.traverse*)(target, mask, op, 0);
}
} /* array_traverse */
Object-oriented programming languages, such as C++, Modula, and Ada,
are well suited to this style of implementation. There should be no
particular difficulty with using a conventional language such as C or
Pascal, however.
<span class="grey">Trewitt & Partridge [Page 41]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-42" ></span>
<span class="grey"><a href="./rfc1076">RFC 1076</a> HEMS Monitoring and Control Language November 1988</span>
III. OBTAINING A COPY OF THE ASN.1 SPECIFICATION
Copies of ISO Standard ASN.1 (Abstract Syntax Notation 1) are
available from the following source. It comes in two parts; both are
needed:
IS 8824 -- Specification (meaning, notation)
IS 8825 -- Encoding Rules (representation)
They are available from:
Omnicom Inc.
115 Park St, S.E. (new address as of March, 1987)
Vienna, VA 22180
(703) 281-1135
Trewitt & Partridge [Page 42]
</pre>
|