Cadena: An Integrated Environment for Developing High-Assurance Component-based Systems

Post on 02-Jan-2016

29 views 3 download

Tags:

description

Cadena: An Integrated Environment for Developing High-Assurance Component-based Systems. SAnToS Laboratory, Kansas State University, USA. http://www.cis.ksu.edu/cadena. Principal Investigators. Postdocs and Students. Radu Iosif Hongjun Zheng Corina Pasareanu Georg Jung. Robby - PowerPoint PPT Presentation

Transcript of Cadena: An Integrated Environment for Developing High-Assurance Component-based Systems

Cadena:An Integrated Environment for

Developing High-Assurance Component-based Systems

http://www.cis.ksu.edu/cadena

Matt DwyerJohn Hatcliff

Principal Investigators

SupportUS National Science Foundation (NSF)US National Aeronautics and Space Agency (NASA)US Department of Defense Advanced Research Projects Agency (DARPA) US Army Research Office (ARO)

Rockwell-Collins ATCHoneywell Technology Center and NASA Langley Sun MicrosystemsIntel

SAnToS Laboratory, Kansas State University, USA

Postdocs and StudentsRadu IosifHongjun ZhengCorina PasareanuGeorg Jung

RobbyVenkatesh RanganathOksana TkachukWilliam Deng

Conclusions Software is moving rapidly towards distributed,

component-based systems Since concurrent/distributed systems are

difficult to reason about, we would like to apply model-checking, static-analyses, and other formal methods

To make this feasible, one needs multiple layers of abstraction (modern systems are huge!)

Interface Definition Languages (e.g., CORBA IDL) provide an excellent hook for attaching light-weight formal specifications

Model-checking modern software (heavily OO) requires using a tool like dSpin

Mission-control software for Boeing military aircraft, e.g., F-18 E/F, Harrier, UCAV

Boeing’s Bold Stroke Avionics Middleware CORBA event-based systems

Focus is developing a rigorous design process with formal design artifacts that can be automatically checked for common design flaws

Analysis & Verification of

Fighter Aircraft Mission Control

Systems

Analysis & Verification of

Fighter Aircraft Mission Control

Systems

Boeing Bold Stroke Platform

Radar

Weapons

Nav Sensors

WeaponManagement

Data Links

Many Computers

Many Computers

Multiple BusesMultiple Buses

Constrained Tactical LinksConstrained

Tactical Links

O(106) Lines of Code

O(106) Lines of CodeHard & Soft

Real-TimeHard & Soft Real-Time

Periodic & Aperiodic

Periodic & Aperiodic

Multiple Safety Criticalities

Multiple Safety Criticalities

Information Security

Information Security

Focus Domain

MissionComputer

VehicleMgmt

COTSCOTS

Software Infrastructure Programmed using a component-based Real-

Time CORBA framework CORBA is middleware

rich infrastructure for building heterogeneous object-oriented distributed systems

Components communicate by publishing/subscribing to events making method calls on component interfaces

Loose coupling addresses a number of issues easier to reuse components, distribution of

resources on aircraft, easy to incorporate real-time aspects, easier to have disjoint groups of developers

Control-Push Data-Pull

Component A computes some data that is to be read by one or more components Bi

Typical situation

Run-time ActionsConfigurationBi subscribe to a dataAvailable event published by ABi connect to an interface of A that provides a getData() method

A

B1

Bk

A publishes a dataAvailable event

Bi call the getData() method of A to fetch the data

dataAvailable

dataAvailable

getData()

getData()

Control-Push Data-Pull Structure

1. Logical GPS component receives a periodic event indicating that it should read the physical GPS device.2. Logical GPS publishes DATA_AVAILABLE event

3. Airframe component fetches GPS data by calling GPS GetData method4. Airframe updates its position data and publishes DATA_AVAILABLE event5. NavDisplay component fetches AirFrame data by calling AirFrame GetData method6. NavDisplay updates the physical display

1

2

3

44

5

6

Larger Configuration

…moving up to 1000+ components

System RequirementsInput Requirements

Very idealized(!), but should give you the flavor

Very idealized(!), but should give you the flavor

The system shall request new inputs from the GPS subsystem at a 40 Hz rate. The system shall poll for a pilot steering mode input at a 1 Hz rate. The system shall receive data from the navigator controls at a 5 Hz rate.

Output Requirements

The system shall disable the display of steering information when deselected by the pilot. When the navigation steering mode is selected, the system shall:

Update navigation steering information display outputs at 20Hz rate based on current airframe data and the current list of navigation points that have been submitted by the navigator. The latency between the GPS data inputs and the display output shall be less than a single 20 Hz frame. The latency between navigation point input and the associated output shall be less than a single 5 Hz frame.

When the tactical steering mode is selected, the system shall: Update tactical steering information display outputs whenever the airframe position data changes.

The system shall display new aircraft position data at a 20 Hz rate. The latency between associated inputs and this output shall be less than a single 20 Hz frame.

System Design Aspects

Declare rates/priorities for intermediate event handlers

Declare rates/priorities for intermediate event handlers

Implement mode semantics for changing subsystem behavior

Implement mode semantics for changing subsystem behavior

Off

AirFrame

Intermediate components correlate incoming data and produce higher-level info

Intermediate components correlate incoming data and produce higher-level info

Inputs triggered @ different rates

Inputs triggered @ different rates

Sensor1

Sensor1

Sensor1

Sensor1

Mode Switch

60Hz

20Hz

5Hz

1Hz

Map components to onboard network nodes

Map components to onboard network nodes

Outputs required

@ different rates

Outputs required

@ different rates

Display

Display

1Hz

20Hz

20Hz

Control

Development Process

Component Development

Component Development

Common Components

Platform-specificComponents

Component IntegrationComponent Integration

Connect components, assign priorities, locking schemes, distribute

Analysis & Functional Testing

Analysis & Functional Testing

Debuggers, call-graph analyzers, scheduling tools

Real Board Testing Real Board Testing

Test real-time aspects, frame-overruns, etc.

Current Challenges Systems with 1000+ components Development team of 100+ developers Process moves directly from informal textual

requirements documents to C++ coding (!) UML artifacts (e.g., collaboration diagrams) are

usually produced only as documentation not automatically analyzed not leveraged in any way to e.g., generate configuration

information usually show partial descriptions and are not maintained

Still resistance by “legacy developers” to higher-level descriptions

moving away from machine code has been difficult for some developers

Research Context Provided with an Open Experimental Platform (OEP)

from Boeing a sanitized version of the real system 100,000+ lines of C++ code (including RT CORBA middleware)

Provided with 150+ page document that outline development process and describe challenge problems

Must provide tool-based solutions that can be applied by Boeing research team realistic systems

Must propose solutions that fit within current development process

Must propose metrics for tool performance and ease of use

evaluation by Boeing research team Must make significant progress in one year with regular

evaluation milestones

Next…

Short-comings in Bold Stroke development that we will attempt to address

Lack of Modeling

Informal natural language requirements

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

C++ component library

XML configurator information

Current development includes little high-level modeling Design errors appear late in development cycle and

correction is more costly what are the ramifications of switching from lazy-active to eager-

active components? what are the ramifications of distributing components to different

boards?

development

Unleveraged Artifacts

Current design/model artifacts are used as informal documentation not connected to analysis/visualization tools not connected to configuration generation not connected to code generation

Lack of Model Analysis

1. Forward & backward data and event dependencies2. Dependency intersections

4. All components from a particular rate group

5. Cycle checks

…15-20 others related to dependencies

Boeing OEP Challenge Problems

3. Components with high data coupling

…also mode-aware dependences

Lack of Model AnalysisBoeing OEP Challenge Problems

If component 1 is in mode A when component 2 produces event E, then component 3 will consume event F

(Section 4.1.5.3.6)

A temporal property!A temporal property!

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

No Unifying Mechanism

C++ Component Code

Bold Stroke XML Configurator Info

?High-level

Specification Language

UML Design Artifacts

Analysis and QoSAspect Synthesis

Integrated Development Environment

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

Cadena

Java/C++ Component Code

Bold Stroke XML Configurator Info

UML Design Artifacts

Analysis and QoSAspect Synthesis

Integrated Development Environment

CCM Interface Definition Language

TAO ExtensionsState

TransitionsSystem

Configuration

Eclipse Plug-In

High-level Specification

Language

Cadena

Example System

Component PortsCORBA 3CCM IDL

event sinkevent sink

eventtype TimeOut {}eventtype DataAvailable {}

interface ReadData { readonly attribute any data;}

component BMDevice { consumes TimeOut timeout publishes DataAvailable dataCurrent provides ReadData dataOut}

Component Ports

eventtype TimeOut {}eventtype DataAvailable {}

interface ReadData { readonly attribute any data;}

component BMDevice { consumes TimeOut timeout publishes DataAvailable dataCurrent provides ReadData dataOut}

CORBA 3CCM IDL

event sourceevent source

Component Ports

eventtype TimeOut {}eventtype DataAvailable {}

interface ReadData { readonly attribute any data;}

component BMDevice { consumes TimeOut timeout publishes DataAvailable dataCurrent provides ReadData dataOut}

CORBA 3CCM IDL

data source(facet)

data source(facet)

Component Code Generation

tacticalSteering : BM__ModalComponent

Push() GetData()

Push() GetData()

Currently in Bold Stroke

=8-12 classes drawn by hand in Rational Rose, then code templates generated from this (component structure must be re-specified each time).

Using CCM IDL Compiler

component BMModal { consumes DataAvailable dataInReady; uses ReadData dataIn; publishes DataAvailable dataOutReady; provides ReadData dataOut; provides Toggle switch;}

Completely auto-generated code templates + component logic

User only fills in body of methods for event-handlers, interfaces

User only fills in body of methods for event-handlers, interfaces

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

abstract distribution nodesabstract distribution nodes

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

rate group declarationrate group declaration

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

create instance of LazyActive component

called AirFrame

create instance of LazyActive component

called AirFrame

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

connect event INPUT port of current component

to event OUTPUT port of GPS component

connect event INPUT port of current component

to event OUTPUT port of GPS component

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

connect data INPUT port of current component

to data OUTPUT port of GPS component

connect data INPUT port of current component

to data OUTPUT port of GPS component

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } … create instance of

DeviceComponent called GPS

create instance of DeviceComponent called

GPS

Cadena Component Assemblysystem ModalSP {

locations l1,l2,l3; rates 1,5,20,60;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

instance GPS of BMDevice on l2 { connect timeout to EventChannel.timeout20 } …

connect event INPUT port of current component

to event OUTPUT port of EventChannel

connect event INPUT port of current component

to event OUTPUT port of EventChannel

Cadena Component Assembly

Cadena Visualization

Glue Code GenerationCurrent Boeing Glue Code Generation

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

<CONFIGURATION_PASS> <HOME> <…> <COMPONENT> <ID> <…></ID> <EVENT_SUPPLIER> <…events this component supplies…> </EVENT_SUPPLIER> </COMPONENT> </HOME></CONFIGURATION_PASS>

Bold Stroke XML Configurator Info

Glue Code

Cadena “Glue Code” Generation

Execution gives allocation and deployment of component instances and connections(complete system)

Glue Code

Code Generation Summary

Component Code Generationcomponent BMModal { consumes DataAvailable dataInReady; uses ReadData dataIn; publishes DataAvailable dataOutReady; provides ReadData dataOut; provides Toggle switch;}

component BMModal { consumes DataAvailable dataInReady; uses ReadData dataIn; publishes DataAvailable dataOutReady; provides ReadData dataOut; provides Toggle switch;} …

component BMModal { consumes DataAvailable dataInReady; uses ReadData dataIn; publishes DataAvailable dataOutReady; provides ReadData dataOut; provides Toggle switch;}

BM.DeviceBM.Device

BM.LazyActiveBM.LazyActive

BM.ModalBM.Modal

“Glue Code” Generation

Execution gives allocation and deployment of component instances and connections(complete system)

Glue Code

Assessment

We’ve done a lot of work already and none of it has to do with model-checking. Tool building + reading CCM spec (1000+

pages!) But…

Boeing developers now have high-level artifacts that definitely want to use (a substantial benefit)

We can now try to “sneak in” formal methods attached to these high-level artifacts

add behavioral annotations to high-level artifacts modify code generation process to generate “cookie-

crumbs” in the code that can be recognized by formal-methods tools to, e.g., help check refinement.

Ultimate Modeling ViewCCM IDLModelLayer

Check mode behaviors, temporal properties, timing constraints

Code Layer

Check that implementations satisfy/refinement high-level specs – leverage the fact that code skeletons are automatically generated

Generate code, fill-in skeletons, check for refinement

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes {enabled,disabled}; Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

input portsinput ports

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

output portsoutput ports

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

mode declaration using CORBA IDL

mode declaration using CORBA IDL

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

behavior for events on dataInReady port

behavior for events on dataInReady port

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

behavior mode casesbehavior mode cases

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } …

data flow specification

data flow specification

Component Behavior

component BMModal { uses ReadData dataIn; consumes DataAvailable inDataAvailable; publishes DataAvailable outDataAvailable; provides ReadData dataOut; provides ChangeMode modeChange;

enum Modes (enabled,disabled); Modes m;

behavior { handles dataInReady (DataAvailable e) { case m of enabled { dataOut::data <- dataIn.getData(); push {} dataOutReady; } disabled {} } … publish eventpublish event

Assessment

CCM IDL, connection information, and behavioral specification are enough to generate precise mode-aware dependence

information generate models suitable for model-

checking model-behavior Seems natural to some one in the

model-checking community Boeing team thought writing behavior

specs would be too much effort(!)

in disabled mode, inDataAvailable triggers no

other port actions

in disabled mode, inDataAvailable triggers no

other port actions

in enabled mode, shows actions triggered by dataIn.get_data()

in enabled mode, shows actions triggered by dataIn.get_data()

triggers no other actions

triggers no other actions

Light-weight Dependency Specs

dependencydefault == all;

dependencies { modeChange() ->; case modeChange.modeVar of { enabled: inDataAvailable -> dataIn.get_data(), outDataAvailable; disabled: inDataAvailable ->; } }

behavior { ... }

Next…

Now, on to modeling…

CORBA Overview

CORBAmiddleware

Distributed, heterogeneous systems

Java

C++

C#C

Java Proxies

Interface Definition LanguageFunctionality

Interface specification for called methods(written in IDL)

CProxies

C#Proxies

C++Proxies

Proxies and middleware take of marshalling & unmarshalling of data and moving data across communication links

Event Channel

Proxy Consumer

Proxy Supplier

GPS(event supplier)

AirFrame(event consumer)

A lot going on behind the scenes…

Event ChannelAutomatically generated

maintains a list of consumers

implements event

correlation

System Model

Event ChannelModel

(same for every system)

Component models (common component models stay same, application-dependent ones are generated for each application)

Event Connections(different for each system)

Event Channel

internal structure of event channel

Function references allow to easily plug in references representing component connections

Function references allow to easily plug in references representing component connections

DSpin Modeling of Components

any NavSteering_internalData;mode NavSteering_componentState;ftype Ref_NavSteering_dataIn1_getData, Ref_NavSteering_dataIn2_getData;ftype Ref_NavSteering_update;

function Fun_NavSteering_source1 (mtype t) { printf("NavSteering: source1 handler invoked.\n"); if :: NavSteering_componentState == enabled -> NavSteering_internalData = Ref_NavSteering_dataIn1_getData (); printf("NavSteering: publishing update.\n"); Ref_NavSteering_update (NavSteering_DataAvailable) :: else fi}

Structure follows component behavior spec and connection representation closely

Structure follows component behavior spec and connection representation closely

DSpin Modeling of Connections

Ref_GPS_dataCurrent = Proxy_GPS_dataCurrent; GPS_dataCurrent_NumberSubscribers = 1; GPS_dataCurrent_SubscriberList = new functionField[1]; GPS_dataCurrent_SubscriberList[0].Entry = Fun_AirFrame_dataAvailable;

instance AirFrame of BMLazyActive on l2 { connect dataAvailable to GPS.dataCurrent atRate 20 connect dataIn to GPS.dataOut

Modeled very directly in DSpin

Functional Properties

Property II: If navSteering is enabled when 20Hz timeout occurs, then airFrame should fetch navSteering data [before end of frame]

Property II: If navSteering is enabled when 20Hz timeout occurs, then airFrame should fetch navSteering data [before end of frame]

Property I:System never reaches a state where TacticalSteering and NavSteering are both disabled

Property I:System never reaches a state where TacticalSteering and NavSteering are both disabled

Temporal Property Specs

Trigger eventTrigger event

…with condition…with condition

Required eventRequired event

“Monitoring” automaton“Monitoring” automaton

Assessment Custom-built (reusable model of event channel)

This is a general approach that we are taking to modeling middle-ware

Component models are automatically generated for each application

System generated tons of infeasible interleavings (priorities/scheduling not taken into account)

took all night to check for deadlock 20million+ states

Enhanced model to include a notion of priority transitions have explicit guards to check for current

priority setting down to 1 million states and finished in a few minutes

Assessment

DSpin models functions and pointers with very little overhead compared to Spin we had an inlined version and the

performance was worse in general, DSpin’s heap representation

incurs little overhead note: garbage collection not required in

this application

Assessment

Encoding explicit scheduling dramatically reduced the number of states BIR model-checker will allow different

scheduling mechanisms to be encoded Encoding of time-aspects is primitive,

but allows checking of interesting functional properties

We are exploring how real-time capabilities can incorporated into BIR checker

Assessment

Why might this technique scale for this application? Even though the number of components

will grow dramatically, there are few threads in thread pool (one per rate group – 4 max)

We are now experimenting with larger scenarios

Conclusions (again!) We have spent extra effort on non-model-checking aspects

to develop a framework where we believe that a variety of formal methods can be applied effectively

model-checking, static-analysis, refinement between specs & code, SAT-solving to check first-order logic predicates constraining component connections

Cadena allows (eventually) end-to-end development of high-assurance CCM distributed systems

We are leveraging a high-level specification format (CCM IDL)

light-weight formal specs can be attached CCM IDL compilation process can be tweaked to insert

“markers” to aid in checking conformance of code to specs Modern software architectures need facilities for functions,

pointers, GC, etc. and these can be incorporated directly into conventional explicit-state model-checking engines

Cadena Capabilities High-level specification of system control

given basic data dependencies, how is control structured to move data from producers to consumers

Multiple ways to leverage modeling information visualization, dependency analysis, model-checking,

component skeleton generation, configuration code generation

Incremental capabilities within an IDE ability to leverage and reason about incomplete specs tools designed to support incremental, iterative

construction System modes and modal behavior

move to more high-level specs instead of having mode implementation distributed to individual componentshttp://www.cis.ksu.edu/santos/cadena