OpenSwitch OPX Developers Guide Release 2.1.
017 - 7 Rev.
Contents 1 Getting started...............................................................................................................................................4 Architecture ....................................................................................................................................................................... 5 Run-time components...........................................................................................................................................
1 Getting started OpenSwitch OPX is implemented using a standard Linux distribution—Debian Jessie. OpenSwitch OPX is binary-compatible with Debian Linux packages. Linux kernel Unmodified Linux kernel included with Debian distribution provides a robust base to support current state-of-theart and future networking. Linux IP stack Rich feature set provided by the Linux standard IP stack without vendor-specific changes.
Architecture The main OpenSwitch OPX components include: • • • • • • • Linux infrastructure Control plane services (CPS) Switch abstraction interface (SAI) Network adaptation service (NAS) System device interface (SDI) Platform adaptation service (PAS) Dell EMC applications and tools Using well-defined APIs allow OpenSwitch OPX to provide full software modularity and abstraction of the hardware and software platforms.
or deleted. The publisher/subscriber approach and object-centric operations allow for the independent operation of client and server applications. The CPS API object model provides disaggregation between client and server applications. The client and server are unaware of one other —they communicate only through a CPS API object (see Client and server applications). Custom-written applications use the CPS API to communicate with OpenSwitch OPX components.
• Read power levels reported by PSUs • Get system inventory and EEPROM information • Set and get operations on transceivers The PAS detects: • Insertion and removal of common field replaceable units (FRUs), such as PSUs and fans • Over-temperature based on pre-defined thresholds • Media insertion on physical ports PAS is responsible for: • Monitoring the status of system devices • Allowing applications to retrieve current status information • Reporting status changes or faults as CPS events
Applications which manage OpenSwitch OPX system components • opx-acl-init — initializes default ACL configuration or control-plane protocol packets • opx-create-interface — gets/sets interface parameters using the CPS API • opx-front-panel-ports — manages physical port mapping to Linux interfaces • opx-ip — gets/sets IP address parameters using the CPS API • opx-phy-media-config — manages configuration of physical media • opx-platform-init — initializes default platform-specific configuration •
System startup OpenSwitch OPX leverages the systemd framework for the startup of OpenSwitch OPX-specific processes. The systemd framework is enabled by default under Debian Jesse (see www.freedesktop.org/wiki/Software/systemd). Boot sequence After you install an OpenSwitch OPX image, the system automatically loads the image and boots. 1 After the switch powers up or reboots, the boot menu displays. After a short delay, the system auto boots by loading the image—in this case OPX-A partition.
2 Programmability The control plane service (CPS) infrastructure is at the core of system programmability. The CPS supports the definition of a well-defined, data-centric application programming interface (CPS API) that allows customer applications to interact with system services. System applications also use the CPS API to communicate with one another.
The TC application increases the speed of a system fan when the value reported by a temperature sensor exceeds a predefined threshold —it decreases the fan speed when the temperature falls below the threshold. The TC application needs to subscribe to temperature threshold crossing events published by the OpenSwitch OPX platform adaptation service (PAS), and invoke a set request to change the speed of the fan object.
Qualifier C enum Symbol String Form Applicability Description Real-Time cps_api_qualifier_RE ALTIME realtime Hardware status attributes and hardware counters Requests values immediately queried from hardware (no caching) Registrations cps_api_qualifier_RE GISTRATION objreg Internal to CPS infrastructure Qualifier used when publishing events associated to object registrations Proposed cps_api_qualifier_PR OPOSED proposed Not applicable Reserved Represent the fixed component of a key in ei
NOTE: Although the Python implementation automatically adds a zero octet to all string values, the C/C++ implementation does not. You must take into account the zero-terminating octet when you use a C/C++ application to set the length of an attribute. CPS qualifiers A CPS qualifier provides the type of object data to retrieve or act on.
• Key 2 {Target, base-ip,ipv4} — Receives all events for objects under IPv4. • Key 3 {Target, base-ip,ipv4,address} — Receives all IPv4 address objects. Multiple applications can subscribe for events that match a specified key. • The infrastructure generates events for CPS-specific conditions when new object owners (server applications) register with the CPS, or objects deregister from the CPS.
The CPS API provides functions for: • Initialization of the CPS services in the context of the calling process • Key management • Object and object attribute handling • CPS event handling and CPS operations Object model representation OpenSwitch OPX uses YANG to represent the object model. YANG object model files are converted to C object model header files, which you use to develop CPS applications. API language support CPS provides Python and C/C++ application programming interfaces.
• Information associated with the element • Model type—attribute, attribute-list, or object • Unique attribute identifier Access the CPS object dictionary in both C/C++ and Python (see CPS API reference). YANG model C header This example shows the C header file generated from the sFlow YANG model by the CPS YANG parser. The sFlow YANG model has two top-level containers: • YANG list named entry • YANG container named socket-address module dell-base-sflow { namespace "http://www.dell.
leaf id{ type uint32; description "Session id to uniquely identify a sflow session"; } leaf ifindex { type base-cmn:logical-ifindex; mandatory true; description "Interface index which uniquely identifies physical interface in the switch where packet sampling needs to to be enabled"; } leaf direction { type base-sflow:traffic-path; mandatory true; description "Direction of packets in which sampling needs to be enabled"; } } leaf sampling-rate{ type uint32; mandatory true; description "Rate at which packets
* not use this file except in compliance with the License. You may obtain * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS * FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. * * See the Apache Version 2.
/*sflow session attributes*/ BASE_SFLOW_ENTRY = 1769478, BASE_SFLOW_ENTRY_OBJ = 1769478, /*Address that sFlow Applications need to open UDP socket on to receive sampled packets. Sampled packets from all sFlow sessions are sent to a single UDP socket.*/ BASE_SFLOW_SOCKET_ADDRESS = 1769481, BASE_SFLOW_SOCKET_ADDRESS_OBJ = 1769481, } BASE_SFLOW_OBJECTS_t; #endif sFlow using YANG and Python This Python example shows how to use a YANG model to configure a new sFlow entry.
• dell-base-phy-interface.yang — Layer 1/physical layer (PHY) interfaces • dell-base-port-security.yang — port security protocols • dell-base-qos.yang — quality of service (QoS) • dell-base-routing.yang — routing protocols • dell-base-sflow.yang — sFlow • dell-base-statistics.yang — diagnostic/statistical information • dell-base-stp.yang — spanning-tree protocols • dell-base-switch-element.yang — global configuration parameters for NPU • dell-base-vlan.yang — VLAN • dell-base-env-tempctl.
3 Application examples This information contains links which describe how to write Python and C/C++ applications using the CPS API application examples. These links contain complete instructions, as well as links to directly view example application files.
7 Verify the return value. ret = transaction.commit() if not transaction: raise RuntimeError ("Error creating Vlan") print "Successfully created" create_vlan.py #Python code block to create VLAN import cps import cps_object #Create CPS Object cps_obj = cps_object.CPSObject('dell-base-if-cmn/if/interfaces/interface') #Populate the attributes for the CPS Object cps_obj.add_attr("base-if-vlan/if/interfaces/interface/id",100) cps_obj.
3 Define the VLAN interface name. VLAN_IF_NAME='br100' cps_obj.add_attr('if/interfaces/interface/name',VLAN_IF_NAME) 4 Define the untagged port to add to the VLAN. if_port_list=['e101-001-0'] cps_obj.add_attr('dell-if/if/interfaces/interface/untagged-ports',if_port_list) 5 Associate a set operation with the CPS object to modify the property of an existing VLAN. cps_update = {'change':cps_obj.get(),'operation': 'set'} 6 Add the CPS operation and object pair to a new CPS transaction. transaction = cps.
dell-if/if/interfaces/interface/learning-mode = 1 if/interfaces/interface/enabled = 0 Verify VLAN port addition using Linux $ brctl show bridge name br100 bridge id 8000.90b11cf4abee STP no enabled interfaces e101-001-0 e101-002-0 e101-003-0 Delete VLAN port using Python 1 Import the CPS and CPS object Python library. import cps import cps_object 2 Create a CPS object. cps_obj = cps_object.CPSObject('dell-base-if-cmn/if/interfaces/interface') 3 Define the VLAN interface name.
Key: 1.19.44.2883617.2883612.2883613. dell-base-if-cmn/if/interfaces/interface/if-index = 47 dell-if/if/interfaces/interface/phys-address = dell-if/if/interfaces/interface/untagged-ports = e101-002-0 base-if-vlan/if/interfaces/interface/id = 100 if/interfaces/interface/name = br100 dell-if/if/interfaces/interface/learning-mode = 1 if/interfaces/interface/enabled = 0 Key: 1.19.44.2883617.2883612.2883613.
ret = transaction.commit() if not transaction: raise RuntimeError ("Error in deleting Vlan") print "successful" Verify VLAN deletion using CPS get # cps_get_oid.py dell-base-if-cmn/if/interfaces/interface if/interfaces/interface/ type=ianaift:l2vlan Key: 1.19.44.2883617.2883612.2883613.
#Verify return value ret = transaction.commit() if not ret: raise RuntimeError ("Error ") Verify IP address using CPS get # cps_get_oid.py 'base-ip/ipv4/address' Key: 1.34.2228241.2228246.2228236.2228240.2228228.
if not ret: raise RuntimeError ("Error ") Verify IP address Deletion using get (return indicates that e101-001-0 has no IP address) $ cps_get_oid.py 'base-ip/ipv4/address' Verify IP address deletion $ ip addr show e101-001-0 16: e101-001-0: mtu 1500 qdisc noop state DOWN group default qlen 500 link/ether 90:b1:1c:f4:aa:b3 brd ff:ff:ff:ff:ff:ff Route application examples NOTE: See the dell-base-route.
obj.add_attr("af", socket.AF_INET6) ip = net.IPNetwork(route_ip) obj.add_attr_type("route-prefix", version) obj.add_attr("route-prefix", str(ip.network)) obj.add_attr("prefix-len", int(ip.prefixlen)) nh_addr = '1.1.1.2' lst = ["nh-list", "0", obj.add_embed_attr(lst, obj.add_attr("nh-count", print obj.get() "nh-addr"] nh_addr) 1) #Create transaction cps_update = ('create', obj.get()) transaction = cps_utils.CPSTransaction([cps_update]) #Verify return value ret = transaction.
obj = cps_utils.CPSObject('base-route/obj/entry') obj.add_attr("vrf-id", 0) if version == 'ipv4': obj.add_attr("af", socket.AF_INET) elif version == 'ipv6': obj.add_attr("af", socket.AF_INET6) ip = net.IPNetwork(route_ip) obj.add_attr_type("route-prefix", version) obj.add_attr("route-prefix", str(ip.network)) obj.add_attr("prefix-len", int(ip.prefixlen)) print obj.get() #Create CPS object and create transaction cps_update = ('delete', obj.get()) transaction = cps_utils.
#Define e_stg = e_ftype e_atype e_ptype enum map {'INGRESS': 1, 'EGRESS': 2} = {'SRC_MAC': 3, 'DST_MAC': 4, 'SRC_IP': 5, 'DST_IP': 6, 'IN_PORT': 9, 'DSCP': 21} = {'PACKET_ACTION': 3, 'SET_TC': 10} = {'DROP': 1} #Tell CPS utility about the type of each attribute type_map = { 'base-acl/entry/SRC_MAC_VALUE/addr': 'mac', 'base-acl/entry/SRC_MAC_VALUE/mask': 'mac', } for key,val in type_map.items(): cps_utils.cps_attr_types_map.
9 Retrieve the CPS object ID from the ACL table — this ID is used for all operations on the ACL table. ret = cps_utils.CPSObject (module='base-acl/table', obj=r[0]['change']) tbl_id = cps_get_val.get_attr_data ('id') print "Successfully created ACL Table " + str(tbl_id) create-acl.py #Python code block to create ACL /usr/bin/python """ Simple Base ACL CPS config using the generic CPS Python module and utilities.
Create ACL entry using Python An ACL entry is a rule that consists of a set of filters that define packets to be matched, and a set of actions to be performed on the matched packets. 1 Import the CPS utility Python library. import cps_utils import nas_os_utils 2 Define the enum map. NOTE: A CPS Python application does not automatically map the YANG model enum name to a number.
10 Verify the return value. ret = cps_trans.commit() if not ret: raise RuntimeError ("Error creating MAC ACL Entry") 11 Retrieve the CPS object ID from the ACL table. This ID is used for all operations on the ACL table. cps_get_val = cps_utils.CPSObject (module='base-acl/entry', obj=r[0]['change']) mac_eid = cps_get_val.get_attr_data ('id') print "Successfully created MAC ACL Entry " + str(mac_eid) create-acl-table.
#Filters #Match Filter 1 - Src MAC cps_obj.add_embed_attr (['match','0','type'], e_ftype['SRC_MAC']) #The 2 at the end indicates that the type should be deducted from the last 2 attrs (SRC_MAC_VALUE,addr) cps_obj.add_embed_attr (['match','0','SRC_MAC_VALUE','addr'], '50:10:6e:00:00:00', 2) #Match Filter 2 - Rx Port cps_obj.add_embed_attr (['match','1','type'], e_ftype['IN_PORT']) cps_obj.add_embed_attr (['match','1','IN_PORT_VALUE'], nas_os_utils.if_nametoindex('e101-001-0')) #Action - Drop cps_obj.
NOTE: A CPS Python application does not automatically map the YANG model enum name to a number. e_stg = e_ftype e_atype e_ptype {'INGRESS': 1, 'EGRESS': 2} = {'SRC_MAC': 3, 'DST_MAC': 4, 'SRC_IP': 5, 'DST_IP': 6, 'IN_PORT': 9, 'DSCP': 21} = {'PACKET_ACTION': 3, 'SET_TC': 10} = {'DROP': 1} 3 Register the attribute type with the CPS utility for attributes with non-integer values. type_map = { 'base-acl/entry/SRC_MAC_VALUE/addr': 'mac', 'base-acl/entry/SRC_MAC_VALUE/mask': 'mac', } for key,val in type_map.
5 Add the operation to the object. tr_obj = ('create', obj.get()) 6 Create a transaction object. transaction = cps_utils.CPSTransaction([tr_obj]) 7 Verify the return value. ret = transaction.commit() if not ret: raise RuntimeError ("Error creating MAC Table Entry") create-mac-table-entry.py #Python block code to create MAC Table entry import cps_utils #Register attribute type cps_utils.
} cps_api_transaction_close(&tran); return false; // Set the key for the object cps_api_object_set_key(obj,&key); // Add attributes mandatory to create MAC address entry uint8_t mac_addr[6] = {0x0,0xa,0xb,0xc,0xd,0xe}; uint16_t vlan_id = 100; cps_api_object_attr_add(obj,BASE_MAC_TABLE_MAC_ADDRESS, mac_addr, sizeof(hal_mac_addr_t)); cps_api_object_attr_add_u32(obj,BASE_MAC_TABLE_IFINDEX,if_nametoindex("e101-001-0")); // Add MAC table VLAN ID cps_api_object_attr_add_u16(obj,BASE_MAC_TABLE_VLAN,vlan_id); //
#Create CPS object obj = cps_utils.CPSObject('base-mac/table',data=d) #Add operation to object tr_obj = ('delete', obj.get()) #Create transaction object transaction = cps_utils.CPSTransaction([tr_obj]) #Verify return value ret = transaction.commit() if not ret: raise RuntimeError("Error deleting entry from MAC Table") delete-mac-table-entry.c // C application example to delete a MAC address table entry #include #include #include #include "cps_api_object.h" "dell-base-l2-mac.h" "cps_class_map.
// Cleanup the Transaction cps_api_transaction_close(&tran); return } true; To delete the MAC address from all VLANs, specify the vlan attribute and its value in the object. To delete all MAC entries from an interface, specify the ifindex attribute and its value in the object. To delete MAC entries from both a VLAN and member interface, specify the vlan and ifindex attributes and their values in the object.
#Verify return value ret = transaction.commit() if not ret: raise RuntimeError("Error Flushing entries from MAC Table") remove-mac-table-entries-from-multiple-vlans.c // C application example to remove MAC address table entries from multiple VLANs #include #include #include #include "cps_api_object.h" "dell-base-l2-mac.h" "cps_class_map.h" "cps_api_object_key.h" #include #include
if(cps_api_action(&tran,obj) != cps_api_ret_code_OK ){ cps_api_object_delete(obj); return false; } // Commit the transaction if(cps_api_commit(&tran) != cps_api_ret_code_OK cps_api_transaction_close(&tran); return false; } ) { // Cleanup the Transaction cps_api_transaction_close(&tran); } return true; Event application examples Register events 1 Import the CPS object Python library. import cps 2 Create a handle to connect to event service. handle = cps.
} char buf[1024]; cps_api_object_to_string(obj,buf,sizeof(buf)); printf("Object Received %s \n",buf); return true; bool cps_reg_intf_events(){ // Initialize the event service if (cps_api_event_service_init() != cps_api_ret_code_OK) return false; } // Initialize the event handling thread if (cps_api_event_thread_init() != cps_api_ret_code_OK) return false; } // Create and initialize the key cps_api_key_t key; cps_api_key_from_attr_with_qual(&key, { { BASE_PORT_INTERFACE_OBJ, cps_api_qualifier_OBSERVED
#Create CPS object obj = cps_utils.CPSObject('base-port/interface',qual='observed', data= #Publish the object cps.event_send(handle, {"ifindex":23}) obj.get()) publish-events.c // C application example to publish events #include #include #include #include #include "cps_api_events.h" "cps_api_object.h" "dell-base-phy-interface.h" "cps_class_map.h" "cps_api_object_key.h" #include #include
4 Application templates Provided are templates to develop applications in Python and C/C++ for server and client applications, and event publishers and event subscribers. Client applications subscribe to events—server applications publish events, and applications can act as both clients and servers.
Event publisher application Template for the structure of a CPS event publisher including initialization of the event service, connection to the object library, and the event publish operation. Event subscriber application Template for the structure of a CPS event subscriber including initialization of the event service and event processing thread, and registration of the event handler function, and event processing callback.
#Obtain handle to CPS API service handle = cps.obj_init() #Register above handlers to be run when a request is received for given key cps.obj_register(handle, key, { get : get_callback, transaction : transaction_callback } ) #Let the handlers run while True: time.sleep(1000) c-template-server-application.
) { /* Extract the object given in the request */ cps_api_object_t request_obj; request_obj = cps_api_object_list_get( param->change_list, index_of_element_being_updated ); if (request_obj == CPS_API_OBJECT_NULL) { /* Failed to extract request object => Indicate error */ return (cps_api_ret_code_ERR); } /* Assume error response */ cps_api_return_code_t result = cps_api_ret_code_ERR; /* Determine the type of write operation */ switch (cps_api_object_type_operation( cps_api_object_key(request_obj) ) ) { case
/* Extract the attribute from the request object */ cps_api_object_attr_t attr; attr = cps_api_object_attr_get(request_obj, attr_id); if (attr == CPS_API_ATTR_NULL)) { /* Failed to extract attribute => Indicate error */ result = cps_api_ret_code_ERR; continue; } /* Extract the value of the attribute in the request object */ value = cps_api_object_attr_data_....(attr); /* Validate the requested attribute value, its consistency with other attributes and/or existing configuration, etc.
); if (rollback_obj == CPS_API_OBJECT_NULL) { /* Failed to extract rollback object => Indicate failure */ return (cps_api_ret_code_ERR); } /* For each attribute to be rolled back, cps_api_object_it_t attr_iter; */ cps_api_object_it_begin(rollback_obj, &attr_iter); while (cps_api_object_it_valid(&attr_iter)) { /* Get the attribute id from the attribute iterator */ cps_api_attr_id_t attr_id; attr_id = cps_api_object_attr_id(attr_iter.
} => Indicate an error */ return (cps_api_ret_code_ERR); /* Allocate a CPS API object registration structure */ cps_api_registration_functions_t reg; /* Assign the key of the CPS API object to be registered */ cps_api_key_init(®.key, ); /* Assign the handler functions to be invoked for this object */ reg._read_function = xyz_read; reg._write_function = xyz_write; reg._rollback_function = xyz_rollback; /* Use obtained handle for CPS API service */ reg.
/* Assume failure response */ cps_api_return_code_t result = cps_api_ret_code_ERR; do { /* Allocate the request object and add it to the get request */ cps_api_object_t request_obj; request_obj = cps_api_object_list_create_obj_and_append( get_req.filters ); if (request_obj == CPS_API_OBJECT_NULL) { /* Failed to allocate response object and add it to get request break; } /* */ */ Set the key and key attributes for the request object.
/* Do something with the extracted value */ /* Indicate success */ result = cps_api_ret_code_OK; } while (0); } cps_api_get_request_close(&get_req); return (result); /****************************************************************** Template to perform CPS API SET *******************************************************************/ cps_api_return_code_t do_set_request() { cps_api_transaction_params_t xact ; if (cps_api_transaction_init(&xact) != return (cps_api_ret_code_ERR); } cps_api_return_code_t
CPS event publisher application templates This information includes templates for the structure of a CPS event publisher. python-event-publisher-application.py #Python code block for CPS event publisher application import cps import cps_utils handle = obj cps_utils.CPSObject('base-port/interface',qual='observed', data= = cps.event_connect() cps.event_send(handle, {"ifindex":23}) obj.get()) c-template-event-publisher-application.
python-event-subscriber-application.py #Python block code for CPS event subscriber application import cps import cps_utils handle = cps.event_connect() cps.event_register(handle, cps_api_object_key) while True: ev = cps.event_wait(handle) if ev[‘key’] == ...: ... elif ev['key'] == ...: ... c-template-event-subscriber-application.
5 Support resources The Dell Networking Support site provides a range of documents and tools to assist you with effectively using Dell Networking devices. Through the support site you can obtain technical information regarding Dell Networking products, access software upgrades and patches, download available management software, and manage your open cases. The Dell Networking support site provides integrated, secure access to these services. To access the Dell Networking Support site, go to www.dell.