•
|
alc — The SR OS-provided packages provide access to various ESM objects such as DHCPv4, DHCPv6 or RADIUS packets.
|
•
|
binascii — Common ASCII decoding like base64.
|
•
|
re — Regular expression support.
|
•
|
struct — Parses and manipulates binary strings.
|
•
|
md5 — MD5 message digest algorithm.
|
import re
import alc
import struct
# ASAM DSLAM circuit ID comes in three flavours:
# FENT string "TLV1: ATM:3/0:100.33"
# GELT octet-stream 0x01010000A0A0A0A0000000640022
# GENT string "ASAM11 atm 1/1/01:100.35"
#
# Script sets output ('subscriber') to 'sub-vpi.vci', e.g.: 'sub-100.33'. circuitid = str(alc.dhcp.options[82][1])
m = re.search(r'(\d+\.\d+)$', circuitid)
if m:
# FENT and GENT
alc.dhcp.sub_ident = "sub-" + m.group()
elif len(circuitid) >= 3:
# GELT
# Note: what byte order does GELT use for the VCI?
# Assume network byte (big endian) order for now. vpi = struct.unpack('B', circuitid[-3:-2])[0]
vci = struct.unpack('>H', circuitid[-2:])[0]
alc.dhcp.sub_ident = "sub-%d.%d" % (vpi, vci)
----------------------------------------------
sub-ident-policy "DSLAM" create
description "Parse circuit IDs from different DSLAMs"
primary
script-url "ftp://xxx.xxx.xxx.xx/py/us5.py"
no shutdown
exit
exit
----------------------------------------------
A:dut-A>config>service>vpls>sap# info
----------------------------------------------
dhcp
description "client side"
lease-populate 50
no shutdown
exit
anti-spoof ip-mac
sub-sla-mgmt
sub-ident-policy "DSLAM"
no shutdown
exit
----------------------------------------------
A:dut-A>config>subscr-mgmt>sub-ident-pol>primary# script-url "ftp://xxx.xxx.xx.xx/py/
parsefail1.py"
A:dut-A>config>subscr-mgmt>sub-ident-pol>primary# no shutdown
1 2006/07/30 01:17:33.14 UTC MINOR: DEBUG #2001 - Python Compile Error
"Python Compile Error: parsefail1.py
File "ftp://xxx.xxx.xx.xx/py/parsefail1.py", line 2 def invalid_function():
^
IndentationError: expected an indented block
"
A:dut-A>config>subscr-mgmt>sub-ident-pol>primary# script-url "ftp://xxx.xxx.xx.xx/py/
dump.py"
2 2006/07/30 01:24:55.50 UTC MINOR: DEBUG #2001 - Python Output
"Python Output: dump.py htype = 0
hlen = 0 hops = 0 flags = 0
ciaddr = '0.0.0.0' yiaddr = '0.0.0.0' siaddr = '0.0.0.0' giaddr = '0.0.0.0' chaddr = ''
sname = ''
file = ''
options = '5\x01\x056\x04\n\x01\x07\n3\x04\x00\x00\x00\xb4\x01\x04\xff\xff\xff
\x00\x1c\x04\n\x02\x02\xffR\x0f\x01\rdut-A|1|1/1/1\xff' "
3 2006/07/30 01:24:55.50 UTC MINOR: DEBUG #2001 - Python Result
"Python Result: dump.py
"
A:dut-A>config>subscr-mgmt>sub-ident-pol>primary# script-url "ftp://xxx.xxx.xx.xx/py/end- less.py"
4 2006/07/30 01:30:17.27 UTC MINOR: DEBUG #2001 - Python Output
"Python Output: endless.py
"
5 2006/07/30 01:30:17.27 UTC MINOR: DEBUG #2001 - Python Error
"Python Error: endless.py
Traceback (most recent call last):
File "ftp://xxx.xxx.xx.xx/py/endless.py", line 2, in ? FatalError: script interrupted (timeout)
"
dump.py —
from alc import dhcp
def print_field(key, value):
print '%-8s = %r' % (key, value)
def ipaddr2a(ipaddr):
return '%d.%d.%d.%d' % (
(ipaddr & 0xFF000000) >> 24, (ipaddr & 0x00FF0000) >> 16, (ipaddr & 0x0000FF00) >> 8, (ipaddr & 0x000000FF))
print_field('htype', dhcp.htype) print_field('hlen', dhcp.hlen) print_field('hops', dhcp.hops) print_field('flags', dhcp.flags) print_field('ciaddr', ipaddr2a(dhcp.ciaddr)) print_field('yiaddr', ipaddr2a(dhcp.yiaddr)) print_field('siaddr', ipaddr2a(dhcp.siaddr)) print_field('giaddr', ipaddr2a(dhcp.giaddr)) print_field('chaddr', dhcp.chaddr) print_field('sname', dhcp.sname) print_field('file', dhcp.file) print_field('options', str(dhcp.options))
us5.py — import re import alc import struct
# ASAM DSLAM circuit ID comes in three flavors:
# FENT string "TLV1: ATM:3/0:100.33"
# GELT octet-stream 0x01010000A0A0A0A0000000640022
# GENT string "ASAM11 atm 1/1/01:100.35"
#
# Script sets output ('subscriber') to 'sub-vpi.vci', e.g.: 'sub-100.33'. circuitid = str(alc.dhcp.options[82][1])
m = re.search(r'(\d+\.\d+)$', circuitid)
if m:
# FENT and GENT
alc.dhcp.sub_ident = "sub-" + m.group()
elif len(circuitid) >= 3:
# GELT
# Note: what byte order does GELT use for the VCI?
# Assume network byte (big endian) order for now. vpi = struct.unpack('B', circuitid[-3:-2])[0]
vci = struct.unpack('>H', circuitid[-2:])[0]
alc.dhcp.sub_ident = "sub-%d.%d" % (vpi, vci)
1. import alc
2. yiaddr = alc.dhcp.yiaddr
3. # Subscriber ID equals full client IP address.
4. # Note: IP address 10.10.10.10 yields 'sub-168430090'
5. # and not 'sub-10.10.10.10'
6. alc.dhcp.sub_ident = 'sub-' + str(yiaddr)
7. # DHCP server is configured such that the third byte (field) of the IP
8. # address indicates the session Profile ID.
9. alc.dhcp.sla_profile_string = 'sp-' + str((yiaddr & 0x0000FF00) >> 8)
Line 1 — Imports the library “alc” – Library imports can reside anywhere in the script as long as the items are imported before they are used.
Line 2— Assigns the decimal value of the host’s IP address to a temporary variable “yiaddr”. Line 6: The text “sub_“ followed by yiaddr is assigned to “sub_ident” string.
Line 9— The text “sp-“ followed with the third byte of the IP address is assigned to the “sla- profile” string.
yiaddr = 10.10.0.2
sub_ident: sub-168427522(hex = A0A00002 = 10.10.0.2)
sla_ident: sp-0
This script returns the sub_profile_string and
sla_profile_string, which are coded directly in the Option 82 string.
1. import re
2. import alc
3. # option 82 formatted as follows:
4. # "<subscriber Profile>-<sla-profile>”
5. ident = str(alc.dhcp.options[82][1])
6. alc.dhcp.sub_ident = ident
7. tmp = re.match("(?P<sub>.+)-(?P<sla>.+)", str(ident))
8. alc.dhcp.sub_profile_string = tmp.group("sub")
9. alc.dhcp.sla_profile_string = tmp.group("sla")
Line 1-2 — Import the libraries “re” and “alc”. Library imports can reside anywhere in the script as long as the items are imported before they are used.
Line 6 — Assigns the full contents of the DHCP Option 82 field to the “sub_ident” variable.
Line 7 — Splits the options 82 string into two parts, separated by “-”.
Line 8 — Assigns the first part of the string to the variable “sub_profile_string”.
Line 9 — Assigns the second part of the string to the variable “sla_profile_string”.
options = \x52\x0D\x01\0x0Bmydsl-video
sub_ident: mydsl-video
sub_profile_string: mydsl
sla_profile_string: video
1. import re
2. import alc
3. import struct
4. # Alcatel 7300 ASAM circuit ID comes in three flavors:
5. # FENT string "TLV1: ATM:3/0:100.33"
6. # GELT octet-stream 0x01010000A0A0A0A0000000640022
7. # GENT string "ASAM11 atm 1/1/01:100.35"
8. #
9. # Script sets output ('subscriber') to 'sub-vpi.vci',
10. # e.g.: 'sub- 100.33'.
11. circuitid = str(alc.dhcp.options[82][1])
12. m = re.search(r'(\d+\.\d+)$', circuitid)
13. if m:
14. # FENT and GENT
15. alc.dhcp.sub_ident = "sub-" + m.group()
16. elif len(circuitid) >= 3:
17. # GELT
18. # Note: GELT uses network byte (big endian) order for the VCI
19. vpi = struct.unpack('B', circuitid[-3:-2])[0]
20. vci = struct.unpack('>H', circuitid[-2:])[0]
21. alc.dhcp.sub_ident = "sub-%d.%d" % (vpi, vci)
Line 1-2 — Import the libraries “re” and “alc” – Library imports can reside anywhere in the script as long as the items are imported before they are used. Needed if regular expressions are used.
Line 3 — Imports the “struct” library, needed if regular expressions are used.
Line 11 — Assigns the contents of the DHCP Option 82 Circuit-ID field to a temporary variable called “circuitid”.
Line 12 — Parses the “circuitid” and checks for the existence of the regular expression “digit.digit” at the end of the string.
Line 15 — If found, a string containing the text “sub-” followed by these two digits is assigned to the variable “sub-ident”.
Line 16 — If not found, and the length of circuit-id is at least 3.
Line 19 — Parses the “circuitid” and assigns the third-last byte to the temporary variable “vpi”.
Line 20 — Parses the “circuitid” and assigns the last two bytes to the temporary variable “vci”.
Line 21 — Assigns a string containing the text “sub-” followed by vpi and vci to the variable “sub-ident”.
options = \x52\x16\x01\x14TLV1: ATM:3/0:100.33
sub_ident: sub-100.33
options = \x52\x10\x01\x0E\x01\x01\x00\x00\xA0\xA0\xA0\xA0\x00\x00\x00\x64 \x00\x22
(in decimal: 82, 16, 1, 15, 1, 1, 0, 0, 160, 160, 160, 160, 0, 0, 0, 100, 0, 34; corresponding to VPI 100, VCI 34)
sub_ident: sub-100.34
options = \x52\x1A\x01\x18ASAM11 atm 1/1/01:100.35
sub_ident: sub-100.35
'%' operator — While %f is supported, %g and %e are not supported.
Floating Point Arithmetic — The floating point arithmetic precision on the box is less than the precision required by the regression suites of Python. For example, pow(2., 30) equals to
The radius-script-policy contains URLs of a primary and optionally a secondary Python script, which could be a local CF file path or a FTP URL. The configured radius-script-policy could be used in different ESM polices like authentication-policy or radius-accounting-policy.
Username=radius.attributes.get(1)
radius.attributes.set(1, 'Tom')
radius.attributes.clear(1)
radius.attributes.set(126,”WIFI-operator”)
config>python# info
----------------------------------------------
python-script "dhcpv4" create
primary-url "cf1:/dhcpv4.py"
no shutdown
exit
python-policy "dhcp" create
dhcp discover direction ingress script "dhcpv4"
dhcp request direction egress script "dhcpv4"
exit
---------------------------------------------
config>service>vprn>sub-if>grp-if>dhcp# info
----------------------------------------------
python-policy "dhcp"
server 9.9.9.9
lease-populate 100
gi-address 192.168.100.1
no shutdown
----------------------------------------------
Option: (82) Agent Information Option
Length: 22
Option (82) Suboption: (1) Agent Circuit ID
Length: 8
Agent Circuit ID: 4a616e737656e73
Option 82 Suboption: (2) Agent Remote ID
Length: 10
Agent Remote ID 62617369632364617461
import alc
option82_list=alc.dhcpv4.get_relayagent()
#option82_list will be [{1:['\x4a\x61\x6e:73\x73\x65\x6e\x73',],2:['\x62\x61\x73\x69\x63\x23\x64\x61\x74\x61',]},]
Option82_list[0][2][0]='basic#video' #change remote-id to 'basic#video'
alc.dhcpv4.set_relayagent(option82_list)#update the option82
Else, if the sub-option is not one of above, then the value to the key is a list of string of sub-option-data, each string represent one instance of the sub-option.
“0f:f0:de:f1:00:02:a3:00:00:04:38:00:00:05:00:18:20:01:05:58:60:45:00:47:45:cc:d9:f2:57:27:ea:e0:00:05:46:00:00:05:46:00”
import alc
iana_list=alc.dhcpv6.get_iana()
#iana_list will be [['\x0f\xf0\xde\xf1','\x00\x02\xa3\x00','\x00\x04\\x38\x00',{5:[['\x20\x01\x05\x58\x60\x45\x00\x47\x45\xcc\xd9\xf2\x57\x27\xea\xe0','\x00\x05\x46\x00','\x00\x05\x46\x00',{}]]}]]
iana_list[0][1]='\x00\x00\x04\xb0' #change T1 to 1200
alc.dhcpv6.set_iana(iana_list)#update the iana
“00:00:00:01:00:00:07:08:00:00:0b:40:00:1a:00:19:00:00:0e:10:00:01:51:80:38:20:01:0d:b8:00:02:00:00:00:00:00:00:00:00:00:00”
import alc
iapd_list=alc.dhcpv6.get_iapd()
#iapd_list will be [['\x00\x00\x00\x01','\x00\x00\x07\x08','\x00\x00\x0b\x40',{26:[['\x00\x00\x0e\x10','\x00\x01\x51\x80','\x38', '\x20\x01\x0d\xb8\x00\x02\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00',{}]]}]]
iapd_list[0][1]='\x00\x00\x04\xb0' #change T1 to 1200
alc.dhcpv6.set_iapd(iapd_list)#update the iapd
“00:00:19:7f:00:01:00:09:69:61:2d:6e:61:5f:30:30:31:00:02:00:09:69:61:2d:70:64:5f:30:30:31:00:03:00:01:38:00:04:00:01:40”
import alc
vendoropts_list=alc.dhcpv6.get_vendoropts()
# vendoropts_list will be [['\x00\x00\x19\x7f', {1:['\x69\x61\x2d\x6e\x61\x5f\x30\x30\x31'],2:[ '\x69\x61\x2d\x70\x64\x5f\x30\x30\x31'],3:['\x38'], 4:['\x40']}]]
iapd_list[0][1][4][0]='\x60' #change sub-option 4’s value to 0x60
alc.dhcpv6.set_vendoropts(vendoropts_list)#update the vendor options
import alc
#input packet is a relay-reply msg
embed_dhcpv6_packet=alc.dhcpv6.get_relaymsg()
iana_list=embed_dhcpv6_packet.get_iana()
iana_list[0][1]='\x00\x00\x04\xb0' #change T1 to 1200
embed_dhcpv6_packet.set_iana(iana_list)#update the iana of the embedded packet
alc.dhcpv6.set_relaymsg(embed_dhcpv6_packet)#update the Relay Message option
import alc
#input packet is a relay-reply msg
embed_lv1_packet=alc.dhcpv6.get_relaymsg() #get the level=1 embedded packet
embed_lv2_packet= embed_lv1_packet.get_relaymsg()#get level-2 packet embedded in level-1 packet
iana_list=embed_dhcpv6_packet.get_iana()
iana_list[0][1]='\x00\x00\x04\xb0' #change T1 to 1200
embed_dhcpv6_packet.set_iana(iana_list)#update the iana
embed_lv1_packet.set_relaymsg(embed_lv2_packet)#update the Relay Message option of lv1 msg
alc.dhcpv6.set_relaymsg(embed_lv1_packet)#update the Relay Message option of the top level msg
•
|
top-level-AVP — AVP appearing at the top level in a Diameter message, i.e. not embedded in the Data field of a grouped AVP
|
•
|
embedded-AVP — AVP embedded in the Data field of a grouped AVP. An embedded AVP can be a grouped AVP. This is called nesting.
|
Table 24 displays attributes available in
alc.diameter module providing access to the Diameter message header:
Table 25 displays methods available in
alc.diameter module providing message and AVP manipulation functionality:
|
|
|
|
|
|
|
|
|
[(263, 0, '@'), (264, 0, '@'), (296, 0, '@'), (258, 0, '@'), (416, 0, '@'), (415, 0, '@'), (268, 0, '@'), (55, 0, '@'), (456, 0, '@'), (456, 0, '@'), (456, 0, '@'), (293, 0, '@'), (256, 12645, '\x80')]
|
|
|
|
[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x00d')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x02')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x03\x84')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x00<')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})]
|
|
[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00d')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x02')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x03\x84')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00<')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})]
|
|
|
|
|
|
|
|
|
|
diameter.set_grouped_avps(456,0,[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00\x2b')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00\x53')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})])
|
configure
aaa
diameter-peer-policy "diameter-peer-policy-1" create
description "Diameter peer policy"
applications gy
origin-host "bng.alcatel-lucent.com"
origin-realm "alcatel-lucent.com"
python-policy "py-policy-diam-1"
source-address 192.0.2.5
peer "peer-1" create
address 172.16.1.1
destination-host "server.alcatel-lucent.com"
destination-realm "alcatel-lucent.com"
no shutdown
exit
exit
exit
configure
python
python-policy "py-policy-diam-1" create
description "Python policy"
diameter ccr direction egress script "diameter-1"
diameter cca direction ingress script "diameter-2"
exit
exit
configure
python
python-script "diameter-1" create
primary-url "ftp://usr:pwd@192.0.2.1/./py/diam-1.py"
no shutdown
exit
exit
from alc import diameter
avp55=diameter.get_avps(55,0)
diameter.set_avps(55,0,[('\x00',avp55[0][1])])
Each cached entry in the cache is a tuple of (key,
val).
key is used as entry id.
val is the string to be cached. Both
key and
val are strings. The max length of the key is 512 bytes. Future more, the combine length of key+val is limited by the configured value of
entry-size size command in the python-policy.
Note: From memory consumption point of view, with MCS enabled, each cached entry will have a corresponding MCS record, so each entry will consume twice amount of memory.
Users can configure protection hmac-sha256 key <key> within a Python script. To mandate, all configured scripts must be in SRPY format.
The system provides a tool command (tool perform python-script protect) to convert a Python script into SRPY format.
# This script takes 2.5 seconds. s = ""
for c in 'A'*50000:
s += str(ord(c)) + ', ' print '[' + s[:-2] + ']'
# This script takes 0.1 seconds. print map(ord, 'A'*50000)