| /* |
| ================================================================================== |
| Copyright (c) 2020 AT&T Intellectual Property. |
| Copyright (c) 2020 Nokia |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may 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 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| This source code is part of the near-RT RIC (RAN Intelligent Controller) |
| platform project (RICP). |
| ================================================================================== |
| */ |
| package main |
| |
| import ( |
| "gerrit.o-ran-sc.org/r/ric-plt/alarm-go.git/alarm" |
| "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientmodel" |
| "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" |
| "net/http" |
| ) |
| |
| // This could be defined in types.go |
| type ExampleXapp struct { |
| msgChan chan *xapp.RMRParams |
| stats map[string]xapp.Counter |
| rmrReady bool |
| waitForSdl bool |
| subscriptionInstances []*clientmodel.SubscriptionInstance |
| subscriptionId *string |
| } |
| |
| func (e *ExampleXapp) handleRICIndication(ranName string, r *xapp.RMRParams) { |
| // Just update metrics and store RMR message payload to SDL |
| e.stats["E2APIndicationsRx"].Inc() |
| |
| xapp.Sdl.Store("myKey", r.Payload) |
| } |
| |
| func (e *ExampleXapp) handleRICExampleMessage(ranName string, r *xapp.RMRParams) { |
| // Just update metrics and echo the message back (update the message type) |
| e.stats["RICExampleMessageRx"].Inc() |
| |
| r.Mtype = r.Mtype + 1 |
| if ok := xapp.Rmr.SendMsg(r); !ok { |
| xapp.Logger.Info("Rmr.SendMsg failed ...") |
| } |
| } |
| |
| func (e *ExampleXapp) messageLoop() { |
| for { |
| msg := <-e.msgChan |
| id := xapp.Rmr.GetRicMessageName(msg.Mtype) |
| defer xapp.Rmr.Free(msg.Mbuf) |
| |
| xapp.Logger.Info("Message received: name=%s meid=%s subId=%d txid=%s len=%d", id, msg.Meid.RanName, msg.SubId, msg.Xid, msg.PayloadLen) |
| |
| switch id { |
| case "RIC_INDICATION": |
| e.handleRICIndication(msg.Meid.RanName, msg) |
| case "RIC_EXAMPLE_MESSAGE": |
| e.handleRICExampleMessage(msg.Meid.RanName, msg) |
| default: |
| xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype) |
| } |
| } |
| } |
| |
| func (e *ExampleXapp) Subscribe() { |
| // Setup response callback to handle subscription response from SubMgr |
| xapp.Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { |
| if *e.subscriptionId == *resp.SubscriptionID { |
| for _, s := range resp.SubscriptionInstances { |
| e.subscriptionInstances = append(e.subscriptionInstances, s) |
| } |
| } |
| }) |
| |
| // Fill subscription parameters: type=REPORT |
| ranName := "en-gnb:369-11105-aaaaa8" |
| functionId := int64(1) |
| clientEndpoint := "localhost:4560" |
| |
| reportParams := clientmodel.ReportParams{ |
| Meid: ranName, |
| RANFunctionID: &functionId, |
| ClientEndpoint: &clientEndpoint, |
| EventTriggers: clientmodel.EventTriggerList{ |
| &clientmodel.EventTrigger{ |
| InterfaceDirection: int64(0), |
| ProcedureCode: int64(27), |
| TypeOfMessage: int64(1), |
| }, |
| }, |
| } |
| |
| // Now subscribe ... |
| if resp, err := xapp.Subscription.SubscribeReport(&reportParams); err == nil { |
| e.subscriptionId = resp.SubscriptionID |
| xapp.Logger.Info("Subscriptions for RanName='%s' [subscriptionId=%s] done!", ranName, *resp.SubscriptionID) |
| return |
| } |
| |
| // Subscription failed, raise alarm (only for demo purpose!) |
| if err := xapp.Alarm.Raise(8006, alarm.SeverityCritical, ranName, "subscriptionFailed"); err != nil { |
| xapp.Logger.Info("Raising alarm failed with error: %v", err) |
| } |
| } |
| |
| func (e *ExampleXapp) Consume(rp *xapp.RMRParams) (err error) { |
| e.msgChan <- rp |
| return |
| } |
| |
| func (u *ExampleXapp) TestRestHandler(w http.ResponseWriter, r *http.Request) { |
| xapp.Logger.Info("TestRestHandler called!") |
| } |
| |
| func (u *ExampleXapp) ConfigChangeHandler(f string) { |
| xapp.Logger.Info("Config file changed, do something meaningful!") |
| } |
| |
| func (u *ExampleXapp) StatusCB() bool { |
| xapp.Logger.Info("Status callback called, do something meaningful!") |
| return true |
| } |
| |
| func (e *ExampleXapp) Run() { |
| // Set MDC (read: name visible in the logs) |
| xapp.Logger.SetMdc("example-xapp", "0.1.3") |
| |
| // Register various callback functions for application management |
| xapp.SetReadyCB(func(d interface{}) { e.rmrReady = true }, true) |
| xapp.AddConfigChangeListener(e.ConfigChangeHandler) |
| xapp.Resource.InjectStatusCb(e.StatusCB) |
| |
| // Inject own REST handler for testing purpose |
| xapp.Resource.InjectRoute("/ric/v1/testing", e.TestRestHandler, "POST") |
| |
| go e.messageLoop() |
| xapp.RunWithParams(e, e.waitForSdl) |
| } |
| |
| func GetMetricsOpts() []xapp.CounterOpts { |
| return []xapp.CounterOpts{ |
| {Name: "RICIndicationsRx", Help: "The total number of RIC inidcation events received"}, |
| {Name: "RICExampleMessageRx", Help: "The total number of RIC example messages received"}, |
| } |
| } |
| |
| func NewExampleXapp(rmrReady bool) *ExampleXapp { |
| metrics := GetMetricsOpts() |
| return &ExampleXapp{ |
| msgChan: make(chan *xapp.RMRParams), |
| stats: xapp.Metric.RegisterCounterGroup(metrics, "ExampleXapp"), |
| rmrReady: rmrReady, |
| waitForSdl: xapp.Config.GetBool("db.waitForSdl"), |
| } |
| } |
| |
| func main() { |
| NewExampleXapp(true).Run() |
| } |